Create generic activity class to simplify handling background tasks
This commit is contained in:
parent
1b4df88916
commit
faa8fb3774
14 changed files with 333 additions and 472 deletions
|
@ -22,19 +22,13 @@
|
||||||
|
|
||||||
package org.shadowice.flocke.andotp.Activities;
|
package org.shadowice.flocke.andotp.Activities;
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import com.google.android.material.textfield.TextInputLayout;
|
import com.google.android.material.textfield.TextInputLayout;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
|
||||||
import androidx.lifecycle.LifecycleOwner;
|
|
||||||
import androidx.lifecycle.ProcessLifecycleOwner;
|
|
||||||
|
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
|
@ -59,17 +53,14 @@ import org.shadowice.flocke.andotp.View.AutoFillable.AutoFillableTextInputEditTe
|
||||||
|
|
||||||
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
|
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
|
||||||
|
|
||||||
public class AuthenticateActivity extends BaseActivity
|
public class AuthenticateActivity extends BackgroundTaskActivity<AuthenticationTask.Result>
|
||||||
implements EditText.OnEditorActionListener, View.OnClickListener {
|
implements EditText.OnEditorActionListener, View.OnClickListener {
|
||||||
private final AutoFillableTextInputEditText.AutoFillTextListener autoFillTextListener = text -> startAuthTask(text.toString());
|
private final AutoFillableTextInputEditText.AutoFillTextListener autoFillTextListener = text -> startAuthTask(text.toString());
|
||||||
|
|
||||||
private static final String TAG_TASK_FRAGMENT = "AuthenticateActivity.TaskFragmentTag";
|
|
||||||
|
|
||||||
private AuthMethod authMethod;
|
private AuthMethod authMethod;
|
||||||
private String newEncryption = "";
|
private String newEncryption = "";
|
||||||
private String existingAuthCredentials;
|
private String existingAuthCredentials;
|
||||||
private boolean isAuthUpgrade = false;
|
private boolean isAuthUpgrade = false;
|
||||||
private ProcessLifecycleObserver observer;
|
|
||||||
|
|
||||||
private TextInputLayout passwordLayout;
|
private TextInputLayout passwordLayout;
|
||||||
AutoFillableTextInputEditText passwordInput;
|
AutoFillableTextInputEditText passwordInput;
|
||||||
|
@ -113,10 +104,6 @@ public class AuthenticateActivity extends BaseActivity
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
observer = new ProcessLifecycleObserver();
|
|
||||||
ProcessLifecycleOwner.get().getLifecycle()
|
|
||||||
.addObserver(observer);
|
|
||||||
|
|
||||||
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
|
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,58 +158,21 @@ public class AuthenticateActivity extends BaseActivity
|
||||||
unlockProgress = v.findViewById(R.id.unlockProgress);
|
unlockProgress = v.findViewById(R.id.unlockProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cancelBackgroundTask() {
|
@Override
|
||||||
TaskFragment taskFragment = findTaskFragment();
|
protected boolean cancelTaskOnScreenOff() {
|
||||||
if (taskFragment != null) {
|
return true;
|
||||||
taskFragment.task.cancel();
|
|
||||||
}
|
|
||||||
setupUiForTaskState(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ProcessLifecycleObserver implements DefaultLifecycleObserver {
|
|
||||||
@Override
|
|
||||||
public void onStop(@NonNull LifecycleOwner owner) {
|
|
||||||
if (settings.getRelockOnBackground()) {
|
|
||||||
cancelBackgroundTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
protected void onReturnToCanceledTask() {
|
||||||
super.onResume();
|
|
||||||
checkBackgroundTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkBackgroundTask() {
|
|
||||||
TaskFragment taskFragment = findTaskFragment();
|
|
||||||
if (taskFragment != null) {
|
|
||||||
if (taskFragment.task.isCanceled()) {
|
|
||||||
// The task was canceled, so remove the task fragment and reset password input.
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.remove(taskFragment)
|
|
||||||
.commit();
|
|
||||||
resetPasswordInput();
|
|
||||||
} else {
|
|
||||||
taskFragment.task.setCallback(this::handleResult);
|
|
||||||
setupUiForTaskState(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetPasswordInput() {
|
|
||||||
passwordInput.setText("");
|
passwordInput.setText("");
|
||||||
passwordInput.requestFocus();
|
passwordInput.requestFocus();
|
||||||
InputMethodManager keyboard = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
InputMethodManager keyboard = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
keyboard.showSoftInput(passwordInput, 0);
|
keyboard.showSoftInput(passwordInput, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Override
|
||||||
private TaskFragment findTaskFragment() {
|
protected void setupUiForTaskState(boolean isTaskRunning) {
|
||||||
return (TaskFragment) getFragmentManager().findFragmentByTag(TAG_TASK_FRAGMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupUiForTaskState(boolean isTaskRunning) {
|
|
||||||
passwordLayout.setEnabled(!isTaskRunning);
|
passwordLayout.setEnabled(!isTaskRunning);
|
||||||
passwordInput.setEnabled(!isTaskRunning);
|
passwordInput.setEnabled(!isTaskRunning);
|
||||||
unlockButton.setEnabled(!isTaskRunning);
|
unlockButton.setEnabled(!isTaskRunning);
|
||||||
|
@ -246,25 +196,12 @@ public class AuthenticateActivity extends BaseActivity
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startAuthTask(String plainPassword) {
|
private void startAuthTask(String plainPassword) {
|
||||||
TaskFragment taskFragment = findTaskFragment();
|
AuthenticationTask task = new AuthenticationTask(this, isAuthUpgrade, existingAuthCredentials, plainPassword);
|
||||||
// Don't start a task if we already have an active task running.
|
startBackgroundTask(task);
|
||||||
if (taskFragment == null || taskFragment.task.isCanceled()) {
|
|
||||||
AuthenticationTask task = new AuthenticationTask(this, isAuthUpgrade, existingAuthCredentials, plainPassword);
|
|
||||||
task.setCallback(this::handleResult);
|
|
||||||
|
|
||||||
if (taskFragment == null) {
|
|
||||||
taskFragment = new TaskFragment();
|
|
||||||
getFragmentManager()
|
|
||||||
.beginTransaction()
|
|
||||||
.add(taskFragment, TAG_TASK_FRAGMENT)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
taskFragment.startTask(task);
|
|
||||||
setupUiForTaskState(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleResult(Result result) {
|
@Override
|
||||||
|
void onTaskResult(Result result) {
|
||||||
if (result.authUpgradeFailed) {
|
if (result.authUpgradeFailed) {
|
||||||
Toast.makeText(this, R.string.settings_toast_auth_upgrade_failed, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.settings_toast_auth_upgrade_failed, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
@ -296,47 +233,14 @@ public class AuthenticateActivity extends BaseActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
// We don't want the task to callback to a dead activity and cause a memory leak, so null it here.
|
|
||||||
TaskFragment taskFragment = findTaskFragment();
|
|
||||||
if (taskFragment != null) {
|
|
||||||
taskFragment.task.setCallback(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
passwordInput.setAutoFillTextListener(null);
|
passwordInput.setAutoFillTextListener(null);
|
||||||
super.onStop();
|
super.onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
ProcessLifecycleOwner.get().getLifecycle()
|
|
||||||
.removeObserver(observer);
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldDestroyOnScreenOff() {
|
protected boolean shouldDestroyOnScreenOff() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retained instance fragment to hold a running {@link AuthenticationTask} between configuration changes.*/
|
|
||||||
public static class TaskFragment extends Fragment {
|
|
||||||
|
|
||||||
AuthenticationTask task;
|
|
||||||
|
|
||||||
public TaskFragment() {
|
|
||||||
super();
|
|
||||||
setRetainInstance(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startTask(@NonNull AuthenticationTask task) {
|
|
||||||
this.task = task;
|
|
||||||
task.execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
package org.shadowice.flocke.andotp.Activities;
|
||||||
|
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||||
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
|
import androidx.lifecycle.ProcessLifecycleOwner;
|
||||||
|
|
||||||
|
import org.shadowice.flocke.andotp.Tasks.UiBasedBackgroundTask;
|
||||||
|
|
||||||
|
public abstract class BackgroundTaskActivity<Result> extends BaseActivity {
|
||||||
|
final protected String TAG_TASK_FRAGMENT = this.getClass().getSimpleName() + ".TaskFragment";
|
||||||
|
|
||||||
|
private ProcessLifecycleObserver observer = null;
|
||||||
|
|
||||||
|
abstract void onTaskResult(Result result);
|
||||||
|
|
||||||
|
protected void onReturnToCanceledTask() {
|
||||||
|
// This can be overwritten if we need to do something here
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setupUiForTaskState(boolean running) {
|
||||||
|
// This can be overwritten when we need to give some UI feedback
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean cancelTaskOnScreenOff() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
if (cancelTaskOnScreenOff()) {
|
||||||
|
observer = new ProcessLifecycleObserver();
|
||||||
|
|
||||||
|
ProcessLifecycleOwner.get().getLifecycle()
|
||||||
|
.addObserver(observer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
if (observer != null) {
|
||||||
|
ProcessLifecycleOwner.get().getLifecycle()
|
||||||
|
.removeObserver(observer);
|
||||||
|
|
||||||
|
observer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
checkBackgroundTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
|
||||||
|
// We don't want the task to callback to a dead activity and cause a memory leak, so null it here.
|
||||||
|
TaskFragment<Result> taskFragment = findTaskFragment();
|
||||||
|
|
||||||
|
if (taskFragment != null)
|
||||||
|
taskFragment.setCallback(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void cancelBackgroundTask() {
|
||||||
|
TaskFragment<Result> taskFragment = findTaskFragment();
|
||||||
|
|
||||||
|
if (taskFragment != null)
|
||||||
|
taskFragment.cancelTask();
|
||||||
|
|
||||||
|
setupUiForTaskState(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startBackgroundTask(UiBasedBackgroundTask<Result> task) {
|
||||||
|
TaskFragment<Result> taskFragment = findTaskFragment();
|
||||||
|
|
||||||
|
// Don't start a task if we already have an active task running.
|
||||||
|
if (taskFragment == null || taskFragment.isCanceled()) {
|
||||||
|
task.setCallback(this::handleTaskResult);
|
||||||
|
|
||||||
|
if (taskFragment == null) {
|
||||||
|
taskFragment = new TaskFragment<>();
|
||||||
|
getFragmentManager()
|
||||||
|
.beginTransaction()
|
||||||
|
.add(taskFragment, TAG_TASK_FRAGMENT)
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
taskFragment.startTask(task);
|
||||||
|
|
||||||
|
setupUiForTaskState(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleTaskResult(Result result) {
|
||||||
|
setupUiForTaskState(false);
|
||||||
|
|
||||||
|
onTaskResult(result);
|
||||||
|
|
||||||
|
// Remove the task fragment after the task is finished
|
||||||
|
TaskFragment<Result> taskFragment = findTaskFragment();
|
||||||
|
|
||||||
|
if (taskFragment != null) {
|
||||||
|
getFragmentManager().beginTransaction()
|
||||||
|
.remove(taskFragment)
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkBackgroundTask() {
|
||||||
|
TaskFragment<Result> taskFragment = findTaskFragment();
|
||||||
|
|
||||||
|
if (taskFragment != null) {
|
||||||
|
if (taskFragment.isCanceled()) {
|
||||||
|
// The task was canceled, so remove the task fragment
|
||||||
|
getFragmentManager().beginTransaction()
|
||||||
|
.remove(taskFragment)
|
||||||
|
.commit();
|
||||||
|
|
||||||
|
onReturnToCanceledTask();
|
||||||
|
|
||||||
|
setupUiForTaskState(false);
|
||||||
|
} else {
|
||||||
|
taskFragment.setCallback(this::handleTaskResult);
|
||||||
|
|
||||||
|
setupUiForTaskState(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setupUiForTaskState(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private TaskFragment<Result> findTaskFragment() {
|
||||||
|
Fragment fragment = getFragmentManager().findFragmentByTag(TAG_TASK_FRAGMENT);
|
||||||
|
|
||||||
|
if (fragment instanceof TaskFragment)
|
||||||
|
return (TaskFragment<Result>) fragment;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ProcessLifecycleObserver implements DefaultLifecycleObserver {
|
||||||
|
@Override
|
||||||
|
public void onStop(@NonNull LifecycleOwner owner) {
|
||||||
|
if (cancelTaskOnScreenOff())
|
||||||
|
cancelBackgroundTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TaskFragment<Result> extends Fragment {
|
||||||
|
private UiBasedBackgroundTask<Result> task;
|
||||||
|
|
||||||
|
public TaskFragment() {
|
||||||
|
super();
|
||||||
|
setRetainInstance(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startTask(@NonNull UiBasedBackgroundTask<Result> task) {
|
||||||
|
this.task = task;
|
||||||
|
task.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallback(@Nullable UiBasedBackgroundTask.UiCallback<Result> callback) {
|
||||||
|
if (this.task != null)
|
||||||
|
this.task.setCallback(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCanceled() {
|
||||||
|
if (task != null)
|
||||||
|
return task.isCanceled();
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelTask() {
|
||||||
|
if (task != null)
|
||||||
|
task.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,6 @@
|
||||||
package org.shadowice.flocke.andotp.Activities;
|
package org.shadowice.flocke.andotp.Activities;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Fragment;
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -31,8 +30,6 @@ import android.content.IntentSender;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -56,10 +53,9 @@ import org.openintents.openpgp.util.OpenPgpServiceConnection;
|
||||||
import org.shadowice.flocke.andotp.Database.Entry;
|
import org.shadowice.flocke.andotp.Database.Entry;
|
||||||
import org.shadowice.flocke.andotp.Dialogs.PasswordEntryDialog;
|
import org.shadowice.flocke.andotp.Dialogs.PasswordEntryDialog;
|
||||||
import org.shadowice.flocke.andotp.R;
|
import org.shadowice.flocke.andotp.R;
|
||||||
|
import org.shadowice.flocke.andotp.Tasks.BackupTaskResult;
|
||||||
import org.shadowice.flocke.andotp.Tasks.EncryptedBackupTask;
|
import org.shadowice.flocke.andotp.Tasks.EncryptedBackupTask;
|
||||||
import org.shadowice.flocke.andotp.Tasks.EncryptedRestoreTask;
|
import org.shadowice.flocke.andotp.Tasks.EncryptedRestoreTask;
|
||||||
import org.shadowice.flocke.andotp.Tasks.GenericBackupTask;
|
|
||||||
import org.shadowice.flocke.andotp.Tasks.GenericRestoreTask;
|
|
||||||
import org.shadowice.flocke.andotp.Tasks.PGPBackupTask;
|
import org.shadowice.flocke.andotp.Tasks.PGPBackupTask;
|
||||||
import org.shadowice.flocke.andotp.Tasks.PGPRestoreTask;
|
import org.shadowice.flocke.andotp.Tasks.PGPRestoreTask;
|
||||||
import org.shadowice.flocke.andotp.Tasks.PlainTextBackupTask;
|
import org.shadowice.flocke.andotp.Tasks.PlainTextBackupTask;
|
||||||
|
@ -79,11 +75,9 @@ import java.util.ArrayList;
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
public class BackupActivity extends BaseActivity {
|
public class BackupActivity extends BackgroundTaskActivity<BackupTaskResult> {
|
||||||
private final static String TAG = BackupActivity.class.getSimpleName();
|
private final static String TAG = BackupActivity.class.getSimpleName();
|
||||||
|
|
||||||
private static final String TAG_TASK_FRAGMENT = "BackupActivity.TaskFragment";
|
|
||||||
|
|
||||||
private Constants.BackupType backupType = Constants.BackupType.ENCRYPTED;
|
private Constants.BackupType backupType = Constants.BackupType.ENCRYPTED;
|
||||||
private SecretKey encryptionKey = null;
|
private SecretKey encryptionKey = null;
|
||||||
|
|
||||||
|
@ -105,6 +99,8 @@ public class BackupActivity extends BaseActivity {
|
||||||
private boolean reload = false;
|
private boolean reload = false;
|
||||||
private boolean allowExit = true;
|
private boolean allowExit = true;
|
||||||
|
|
||||||
|
private BackupTaskResult.ResultType currentTask = BackupTaskResult.ResultType.NONE;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
@ -276,29 +272,28 @@ public class BackupActivity extends BaseActivity {
|
||||||
Toast.makeText(this, msgId, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, msgId, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleBackupTaskResult(GenericBackupTask.BackupTaskResult result) {
|
@Override
|
||||||
showBackupProgress(false);
|
void onTaskResult(BackupTaskResult backupTaskResult) {
|
||||||
|
if (backupTaskResult.resultType == BackupTaskResult.ResultType.BACKUP)
|
||||||
|
handleBackupTaskResult(backupTaskResult);
|
||||||
|
else if (backupTaskResult.resultType == BackupTaskResult.ResultType.RESTORE)
|
||||||
|
handleRestoreTaskResult(backupTaskResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleBackupTaskResult(BackupTaskResult result) {
|
||||||
if (result.messageId != 0)
|
if (result.messageId != 0)
|
||||||
notifyBackupState(result.messageId);
|
notifyBackupState(result.messageId);
|
||||||
else
|
else
|
||||||
if (!result.success)
|
if (result.success)
|
||||||
|
notifyBackupState(R.string.backup_toast_export_success);
|
||||||
|
else
|
||||||
notifyBackupState(R.string.backup_toast_export_failed);
|
notifyBackupState(R.string.backup_toast_export_failed);
|
||||||
|
|
||||||
// Clean up the task fragment
|
|
||||||
TaskFragment taskFragment = findTaskFragment();
|
|
||||||
|
|
||||||
if (taskFragment != null && taskFragment.isEmpty()) {
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.remove(taskFragment)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.success)
|
if (result.success)
|
||||||
finishWithResult();
|
finishWithResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleRestoreTaskResult(GenericRestoreTask.RestoreTaskResult result) {
|
private void handleRestoreTaskResult(BackupTaskResult result) {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
if (result.isPGP) {
|
if (result.isPGP) {
|
||||||
InputStream is = new ByteArrayInputStream(result.payload.getBytes(StandardCharsets.UTF_8));
|
InputStream is = new ByteArrayInputStream(result.payload.getBytes(StandardCharsets.UTF_8));
|
||||||
|
@ -318,20 +313,23 @@ public class BackupActivity extends BaseActivity {
|
||||||
notifyBackupState(R.string.backup_toast_import_failed);
|
notifyBackupState(R.string.backup_toast_import_failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
showRestoreProgress(false);
|
|
||||||
|
|
||||||
// Clean up the task fragment
|
|
||||||
TaskFragment taskFragment = findTaskFragment();
|
|
||||||
if (taskFragment != null && taskFragment.isEmpty()) {
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.remove(taskFragment)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.success && !result.isPGP)
|
if (result.success && !result.isPGP)
|
||||||
finishWithResult();
|
finishWithResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setupUiForTaskState(boolean running) {
|
||||||
|
if (currentTask == BackupTaskResult.ResultType.BACKUP)
|
||||||
|
showBackupProgress(running);
|
||||||
|
else if (currentTask == BackupTaskResult.ResultType.RESTORE)
|
||||||
|
showRestoreProgress(running);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startBackgroundTask(UiBasedBackgroundTask<BackupTaskResult> task, BackupTaskResult.ResultType type) {
|
||||||
|
currentTask = type;
|
||||||
|
startBackgroundTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
private void toggleInProgressMode(boolean running) {
|
private void toggleInProgressMode(boolean running) {
|
||||||
allowExit = !running;
|
allowExit = !running;
|
||||||
|
|
||||||
|
@ -465,9 +463,7 @@ public class BackupActivity extends BaseActivity {
|
||||||
private void doRestorePlain(Uri uri) {
|
private void doRestorePlain(Uri uri) {
|
||||||
if (Tools.isExternalStorageReadable()) {
|
if (Tools.isExternalStorageReadable()) {
|
||||||
PlainTextRestoreTask task = new PlainTextRestoreTask(this, uri);
|
PlainTextRestoreTask task = new PlainTextRestoreTask(this, uri);
|
||||||
task.setCallback(this::handleRestoreTaskResult);
|
startBackgroundTask(task, BackupTaskResult.ResultType.RESTORE);
|
||||||
|
|
||||||
startRestoreTask(task);
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
@ -478,9 +474,7 @@ public class BackupActivity extends BaseActivity {
|
||||||
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(this, encryptionKey);
|
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(this, encryptionKey);
|
||||||
|
|
||||||
PlainTextBackupTask task = new PlainTextBackupTask(this, entries, uri);
|
PlainTextBackupTask task = new PlainTextBackupTask(this, entries, uri);
|
||||||
task.setCallback(this::handleBackupTaskResult);
|
startBackgroundTask(task, BackupTaskResult.ResultType.BACKUP);
|
||||||
|
|
||||||
startBackupTask(task);
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
@ -514,9 +508,7 @@ public class BackupActivity extends BaseActivity {
|
||||||
private void doRestoreCryptWithPassword(Uri uri, String password, boolean old_format) {
|
private void doRestoreCryptWithPassword(Uri uri, String password, boolean old_format) {
|
||||||
if (Tools.isExternalStorageReadable()) {
|
if (Tools.isExternalStorageReadable()) {
|
||||||
EncryptedRestoreTask task = new EncryptedRestoreTask(this, uri, password, old_format);
|
EncryptedRestoreTask task = new EncryptedRestoreTask(this, uri, password, old_format);
|
||||||
task.setCallback(this::handleRestoreTaskResult);
|
startBackgroundTask(task, BackupTaskResult.ResultType.RESTORE);
|
||||||
|
|
||||||
startRestoreTask(task);
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
@ -538,9 +530,7 @@ public class BackupActivity extends BaseActivity {
|
||||||
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(this, encryptionKey);
|
ArrayList<Entry> entries = DatabaseHelper.loadDatabase(this, encryptionKey);
|
||||||
|
|
||||||
EncryptedBackupTask task = new EncryptedBackupTask(this, entries, password, uri);
|
EncryptedBackupTask task = new EncryptedBackupTask(this, entries, password, uri);
|
||||||
task.setCallback(this::handleBackupTaskResult);
|
startBackgroundTask(task, BackupTaskResult.ResultType.BACKUP);
|
||||||
|
|
||||||
startBackupTask(task);
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
@ -553,17 +543,13 @@ public class BackupActivity extends BaseActivity {
|
||||||
decryptIntent = new Intent(OpenPgpApi.ACTION_DECRYPT_VERIFY);
|
decryptIntent = new Intent(OpenPgpApi.ACTION_DECRYPT_VERIFY);
|
||||||
|
|
||||||
PGPRestoreTask task = new PGPRestoreTask(this, uri, decryptIntent);
|
PGPRestoreTask task = new PGPRestoreTask(this, uri, decryptIntent);
|
||||||
task.setCallback(this::handleRestoreTaskResult);
|
startBackgroundTask(task, BackupTaskResult.ResultType.RESTORE);
|
||||||
|
|
||||||
startRestoreTask(task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doBackupEncrypted(Uri uri, String data) {
|
private void doBackupEncrypted(Uri uri, String data) {
|
||||||
if (Tools.isExternalStorageWritable()) {
|
if (Tools.isExternalStorageWritable()) {
|
||||||
PGPBackupTask task = new PGPBackupTask(this, data, uri);
|
PGPBackupTask task = new PGPBackupTask(this, data, uri);
|
||||||
task.setCallback(this::handleBackupTaskResult);
|
startBackgroundTask(task, BackupTaskResult.ResultType.BACKUP);
|
||||||
|
|
||||||
startBackupTask(task);
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.backup_toast_storage_not_accessible, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
@ -645,127 +631,8 @@ public class BackupActivity extends BaseActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private TaskFragment findTaskFragment() {
|
|
||||||
return (TaskFragment) getFragmentManager().findFragmentByTag(TAG_TASK_FRAGMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startBackupTask(GenericBackupTask task) {
|
|
||||||
TaskFragment taskFragment = findTaskFragment();
|
|
||||||
|
|
||||||
// Don't start a task if we already have an active task running (backup or restore).
|
|
||||||
if (taskFragment == null || taskFragment.isEmpty()) {
|
|
||||||
if (taskFragment == null) {
|
|
||||||
taskFragment = new TaskFragment();
|
|
||||||
getFragmentManager()
|
|
||||||
.beginTransaction()
|
|
||||||
.add(taskFragment, TAG_TASK_FRAGMENT)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
taskFragment.startBackupTask(task);
|
|
||||||
showBackupProgress(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startRestoreTask(GenericRestoreTask task) {
|
|
||||||
TaskFragment taskFragment = findTaskFragment();
|
|
||||||
|
|
||||||
// Don't start a task if we already have an active task running (backup or restore).
|
|
||||||
if (taskFragment == null || taskFragment.isEmpty()) {
|
|
||||||
if (taskFragment == null) {
|
|
||||||
taskFragment = new TaskFragment();
|
|
||||||
getFragmentManager()
|
|
||||||
.beginTransaction()
|
|
||||||
.add(taskFragment, TAG_TASK_FRAGMENT)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
taskFragment.startRestoreTask(task);
|
|
||||||
showRestoreProgress(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkBackgroundTask() {
|
|
||||||
TaskFragment taskFragment = findTaskFragment();
|
|
||||||
|
|
||||||
if (taskFragment != null) {
|
|
||||||
if (taskFragment.isEmpty()) {
|
|
||||||
// The task was canceled or has finished, so remove the task fragment.
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.remove(taskFragment)
|
|
||||||
.commit();
|
|
||||||
} else {
|
|
||||||
if (taskFragment.isRestoreRunning())
|
|
||||||
showRestoreProgress(true);
|
|
||||||
|
|
||||||
if (taskFragment.isBackupRunning())
|
|
||||||
showBackupProgress(true);
|
|
||||||
|
|
||||||
taskFragment.setCallbacks(this::handleBackupTaskResult, this::handleRestoreTaskResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
|
|
||||||
// We don't want the task to callback to a dead activity and cause a memory leak, so null it here.
|
|
||||||
TaskFragment taskFragment = findTaskFragment();
|
|
||||||
|
|
||||||
if (taskFragment != null)
|
|
||||||
taskFragment.setCallbacks(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
checkBackgroundTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldDestroyOnScreenOff() {
|
protected boolean shouldDestroyOnScreenOff() {
|
||||||
return allowExit; // Don't destroy the backup activity as long as a backup task is running
|
return allowExit; // Don't destroy the backup activity as long as a backup task is running
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TaskFragment extends Fragment {
|
|
||||||
GenericBackupTask backupTask;
|
|
||||||
GenericRestoreTask restoreTask;
|
|
||||||
|
|
||||||
public TaskFragment() {
|
|
||||||
super();
|
|
||||||
setRetainInstance(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCallbacks(UiBasedBackgroundTask.UiCallback<GenericBackupTask.BackupTaskResult> backupCallback, UiBasedBackgroundTask.UiCallback<GenericRestoreTask.RestoreTaskResult> restoreCallback) {
|
|
||||||
if (backupTask != null && backupTask.isRunning())
|
|
||||||
backupTask.setCallback(backupCallback);
|
|
||||||
|
|
||||||
if (restoreTask != null && restoreTask.isRunning())
|
|
||||||
restoreTask.setCallback(restoreCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return ((backupTask == null || !backupTask.isRunning()) && (restoreTask == null || !restoreTask.isRunning()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRestoreRunning() {
|
|
||||||
return (restoreTask != null && restoreTask.isRunning());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBackupRunning() {
|
|
||||||
return (backupTask != null && backupTask.isRunning());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startBackupTask(@NonNull GenericBackupTask task) {
|
|
||||||
this.backupTask = task;
|
|
||||||
this.backupTask.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startRestoreTask(@NonNull GenericRestoreTask task) {
|
|
||||||
this.restoreTask = task;
|
|
||||||
this.restoreTask.execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
package org.shadowice.flocke.andotp.Activities;
|
package org.shadowice.flocke.andotp.Activities;
|
||||||
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.app.backup.BackupManager;
|
import android.app.backup.BackupManager;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -39,13 +38,14 @@ import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
import android.provider.DocumentsContract;
|
import android.provider.DocumentsContract;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ViewStub;
|
import android.view.ViewStub;
|
||||||
import android.widget.Toast;
|
|
||||||
|
import com.google.android.material.snackbar.BaseTransientBottomBar;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
import org.openintents.openpgp.util.OpenPgpAppPreference;
|
import org.openintents.openpgp.util.OpenPgpAppPreference;
|
||||||
import org.openintents.openpgp.util.OpenPgpKeyPreference;
|
import org.openintents.openpgp.util.OpenPgpKeyPreference;
|
||||||
|
@ -67,18 +67,16 @@ import javax.crypto.SecretKey;
|
||||||
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
|
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
|
||||||
import static org.shadowice.flocke.andotp.Utilities.Constants.EncryptionType;
|
import static org.shadowice.flocke.andotp.Utilities.Constants.EncryptionType;
|
||||||
|
|
||||||
public class SettingsActivity extends BaseActivity
|
public class SettingsActivity extends BackgroundTaskActivity<ChangeEncryptionTask.Result>
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener, EncryptionHelper.EncryptionChangeCallback {
|
implements SharedPreferences.OnSharedPreferenceChangeListener, EncryptionHelper.EncryptionChangeCallback {
|
||||||
|
|
||||||
private static final String TAG_TASK_FRAGMENT = "SettingsActivity.TaskFragmentTag";
|
|
||||||
|
|
||||||
private SettingsFragment fragment;
|
private SettingsFragment fragment;
|
||||||
private SharedPreferences prefs;
|
private SharedPreferences prefs;
|
||||||
|
|
||||||
private SecretKey encryptionKey = null;
|
private SecretKey encryptionKey = null;
|
||||||
private boolean encryptionChanged = false;
|
private boolean encryptionChanged = false;
|
||||||
|
|
||||||
private Toast inProgress = null;
|
private Snackbar inProgress = null;
|
||||||
private boolean canGoBack = true;
|
private boolean canGoBack = true;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -189,7 +187,7 @@ public class SettingsActivity extends BaseActivity
|
||||||
(settings.getAndroidBackupServiceEnabled() ? "enabled" : "disabled"));
|
(settings.getAndroidBackupServiceEnabled() ? "enabled" : "disabled"));
|
||||||
|
|
||||||
int message = settings.getAndroidBackupServiceEnabled() ? R.string.settings_toast_android_sync_enabled : R.string.settings_toast_android_sync_disabled;
|
int message = settings.getAndroidBackupServiceEnabled() ? R.string.settings_toast_android_sync_enabled : R.string.settings_toast_android_sync_disabled;
|
||||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
Snackbar.make(fragment.getView(), message, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment.updateAutoBackup();
|
fragment.updateAutoBackup();
|
||||||
|
@ -218,106 +216,43 @@ public class SettingsActivity extends BaseActivity
|
||||||
fragment.setEncryptionKey(newEncryptionKey);
|
fragment.setEncryptionKey(newEncryptionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleTaskResult(ChangeEncryptionTask.Result result) {
|
@Override
|
||||||
setupUiForTaskState(false);
|
void onTaskResult(ChangeEncryptionTask.Result result) {
|
||||||
|
|
||||||
switch (result.result) {
|
switch (result.result) {
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
onSuccessfulEncryptionChange(result.encryptionType, result.newEncryptionKey);
|
onSuccessfulEncryptionChange(result.encryptionType, result.newEncryptionKey);
|
||||||
Toast.makeText(this, R.string.settings_toast_encryption_change_success, Toast.LENGTH_LONG).show();
|
Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_change_success, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||||
break;
|
break;
|
||||||
case BACKUP_FAILURE:
|
case BACKUP_FAILURE:
|
||||||
Toast.makeText(this, R.string.settings_toast_encryption_backup_failed, Toast.LENGTH_LONG).show();
|
Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_backup_failed, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||||
break;
|
break;
|
||||||
case CHANGE_FAILURE:
|
case CHANGE_FAILURE:
|
||||||
Toast.makeText(this, R.string.settings_toast_encryption_change_failed, Toast.LENGTH_LONG).show();
|
Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_change_failed, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the task fragment after the task is finished
|
|
||||||
TaskFragment taskFragment = findTaskFragment();
|
|
||||||
if (taskFragment != null) {
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.remove(taskFragment)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private SettingsActivity.TaskFragment findTaskFragment() {
|
|
||||||
return (SettingsActivity.TaskFragment) getFragmentManager().findFragmentByTag(TAG_TASK_FRAGMENT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startEncryptionChangeTask(EncryptionType newEnc, byte[] newKey) {
|
private void startEncryptionChangeTask(EncryptionType newEnc, byte[] newKey) {
|
||||||
SettingsActivity.TaskFragment taskFragment = findTaskFragment();
|
ChangeEncryptionTask task = new ChangeEncryptionTask(this, encryptionKey, newEnc, newKey);
|
||||||
// Don't start a task if we already have an active task running.
|
startBackgroundTask(task);
|
||||||
if (taskFragment == null || taskFragment.task.isCanceled()) {
|
|
||||||
ChangeEncryptionTask task = new ChangeEncryptionTask(this, encryptionKey, newEnc, newKey);
|
|
||||||
task.setCallback(this::handleTaskResult);
|
|
||||||
|
|
||||||
if (taskFragment == null) {
|
|
||||||
taskFragment = new SettingsActivity.TaskFragment();
|
|
||||||
getFragmentManager()
|
|
||||||
.beginTransaction()
|
|
||||||
.add(taskFragment, TAG_TASK_FRAGMENT)
|
|
||||||
.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
taskFragment.startTask(task);
|
|
||||||
setupUiForTaskState(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBackgroundTask() {
|
@Override
|
||||||
SettingsActivity.TaskFragment taskFragment = findTaskFragment();
|
protected void setupUiForTaskState(boolean taskRunning) {
|
||||||
|
|
||||||
if (taskFragment != null) {
|
|
||||||
if (taskFragment.task.isCanceled()) {
|
|
||||||
// The task was canceled, so remove the task fragment
|
|
||||||
getFragmentManager().beginTransaction()
|
|
||||||
.remove(taskFragment)
|
|
||||||
.commit();
|
|
||||||
setupUiForTaskState(false);
|
|
||||||
} else {
|
|
||||||
taskFragment.task.setCallback(this::handleTaskResult);
|
|
||||||
setupUiForTaskState(true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setupUiForTaskState(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupUiForTaskState(boolean taskRunning) {
|
|
||||||
if (taskRunning) {
|
if (taskRunning) {
|
||||||
canGoBack = false;
|
|
||||||
|
|
||||||
// TODO: Better in-progress notification
|
// TODO: Better in-progress notification
|
||||||
inProgress = Toast.makeText(this, R.string.settings_toast_encryption_changing, Toast.LENGTH_LONG);
|
inProgress = Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_changing, BaseTransientBottomBar.LENGTH_INDEFINITE);
|
||||||
inProgress.show();
|
inProgress.show();
|
||||||
|
|
||||||
|
canGoBack = false;
|
||||||
} else {
|
} else {
|
||||||
canGoBack = true;
|
|
||||||
|
|
||||||
if (inProgress != null)
|
if (inProgress != null)
|
||||||
inProgress.cancel();
|
inProgress.dismiss();
|
||||||
|
|
||||||
|
canGoBack = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
checkBackgroundTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
// We don't want the task to callback to a dead activity and cause a memory leak, so null it here.
|
|
||||||
SettingsActivity.TaskFragment taskFragment = findTaskFragment();
|
|
||||||
|
|
||||||
if (taskFragment != null)
|
|
||||||
taskFragment.task.setCallback(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void requestBackupAccess() {
|
private void requestBackupAccess() {
|
||||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
@ -344,10 +279,10 @@ public class SettingsActivity extends BaseActivity
|
||||||
EncryptionType newEncType = EncryptionType.valueOf(newEnc);
|
EncryptionType newEncType = EncryptionType.valueOf(newEnc);
|
||||||
startEncryptionChangeTask(newEncType, authKey);
|
startEncryptionChangeTask(newEncType, authKey);
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.settings_toast_encryption_no_key, Toast.LENGTH_LONG).show();
|
Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_no_key, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.settings_toast_encryption_auth_failed, Toast.LENGTH_LONG).show();
|
Snackbar.make(fragment.getView(), R.string.settings_toast_encryption_auth_failed, BaseTransientBottomBar.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
} else if (requestCode == Constants.INTENT_SETTINGS_BACKUP_LOCATION && resultCode == RESULT_OK) {
|
} else if (requestCode == Constants.INTENT_SETTINGS_BACKUP_LOCATION && resultCode == RESULT_OK) {
|
||||||
Uri treeUri = data.getData();
|
Uri treeUri = data.getData();
|
||||||
|
@ -573,19 +508,4 @@ public class SettingsActivity extends BaseActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retained instance fragment to hold a running {@link ChangeEncryptionTask} between configuration changes.*/
|
|
||||||
public static class TaskFragment extends Fragment {
|
|
||||||
ChangeEncryptionTask task;
|
|
||||||
|
|
||||||
public TaskFragment() {
|
|
||||||
super();
|
|
||||||
setRetainInstance(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startTask(@NonNull ChangeEncryptionTask task) {
|
|
||||||
this.task = task;
|
|
||||||
task.execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,8 @@ import android.content.Intent;
|
||||||
|
|
||||||
import org.shadowice.flocke.andotp.Database.Entry;
|
import org.shadowice.flocke.andotp.Database.Entry;
|
||||||
import org.shadowice.flocke.andotp.R;
|
import org.shadowice.flocke.andotp.R;
|
||||||
|
import org.shadowice.flocke.andotp.Tasks.BackupTaskResult;
|
||||||
import org.shadowice.flocke.andotp.Tasks.EncryptedBackupTask;
|
import org.shadowice.flocke.andotp.Tasks.EncryptedBackupTask;
|
||||||
import org.shadowice.flocke.andotp.Tasks.GenericBackupTask;
|
|
||||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||||
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
||||||
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
|
import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
|
||||||
|
@ -81,9 +81,9 @@ public class EncryptedBackupBroadcastReceiver extends BackupBroadcastReceiver {
|
||||||
task.execute();
|
task.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleTaskResult(GenericBackupTask.BackupTaskResult result) {
|
private void handleTaskResult(BackupTaskResult result) {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_SUCCESS, R.string.backup_receiver_title_backup_success, result.fileName);
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_SUCCESS, R.string.backup_receiver_title_backup_success, result.payload);
|
||||||
} else {
|
} else {
|
||||||
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, result.messageId);
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, result.messageId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import android.content.Intent;
|
||||||
|
|
||||||
import org.shadowice.flocke.andotp.Database.Entry;
|
import org.shadowice.flocke.andotp.Database.Entry;
|
||||||
import org.shadowice.flocke.andotp.R;
|
import org.shadowice.flocke.andotp.R;
|
||||||
import org.shadowice.flocke.andotp.Tasks.GenericBackupTask;
|
import org.shadowice.flocke.andotp.Tasks.BackupTaskResult;
|
||||||
import org.shadowice.flocke.andotp.Tasks.PlainTextBackupTask;
|
import org.shadowice.flocke.andotp.Tasks.PlainTextBackupTask;
|
||||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||||
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
||||||
|
@ -74,9 +74,9 @@ public class PlainTextBackupBroadcastReceiver extends BackupBroadcastReceiver {
|
||||||
task.execute();
|
task.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleTaskResult(GenericBackupTask.BackupTaskResult result) {
|
private void handleTaskResult(BackupTaskResult result) {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_SUCCESS, R.string.backup_receiver_title_backup_success, result.fileName);
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_SUCCESS, R.string.backup_receiver_title_backup_success, result.payload);
|
||||||
} else {
|
} else {
|
||||||
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, result.messageId);
|
NotificationHelper.notify(context, Constants.NotificationChannel.BACKUP_FAILED, R.string.backup_receiver_title_backup_failed, result.messageId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package org.shadowice.flocke.andotp.Tasks;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import org.shadowice.flocke.andotp.R;
|
||||||
|
|
||||||
|
public class BackupTaskResult {
|
||||||
|
public final boolean success;
|
||||||
|
public final String payload;
|
||||||
|
public final int messageId;
|
||||||
|
|
||||||
|
public boolean isPGP = false;
|
||||||
|
public Intent decryptIntent = null;
|
||||||
|
public Uri uri = null;
|
||||||
|
|
||||||
|
public final ResultType resultType;
|
||||||
|
|
||||||
|
public enum ResultType {
|
||||||
|
NONE, BACKUP, RESTORE
|
||||||
|
}
|
||||||
|
|
||||||
|
public BackupTaskResult(ResultType type, boolean success, String payload, int messageId) {
|
||||||
|
this.resultType = type;
|
||||||
|
this.success = success;
|
||||||
|
this.payload = payload;
|
||||||
|
this.messageId = messageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BackupTaskResult(ResultType type, boolean success, String payload, int messageId, boolean isPGP, Intent decryptIntent, Uri uri) {
|
||||||
|
this.resultType = type;
|
||||||
|
this.success = success;
|
||||||
|
this.payload = payload;
|
||||||
|
this.messageId = messageId;
|
||||||
|
this.isPGP = isPGP;
|
||||||
|
this.decryptIntent = decryptIntent;
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BackupTaskResult success(ResultType type, String payload) {
|
||||||
|
return new BackupTaskResult(type, true, payload, R.string.backup_toast_export_success);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BackupTaskResult failure(ResultType type, int messageId) {
|
||||||
|
return new BackupTaskResult(type, false, null, messageId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ public class EncryptedRestoreTask extends GenericRestoreTask {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
protected RestoreTaskResult doInBackground() {
|
protected BackupTaskResult doInBackground() {
|
||||||
boolean success = true;
|
boolean success = true;
|
||||||
String decryptedString = "";
|
String decryptedString = "";
|
||||||
|
|
||||||
|
@ -58,9 +58,9 @@ public class EncryptedRestoreTask extends GenericRestoreTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
return RestoreTaskResult.success(decryptedString);
|
return BackupTaskResult.success(BackupTaskResult.ResultType.RESTORE, decryptedString);
|
||||||
} else {
|
} else {
|
||||||
return RestoreTaskResult.failure(R.string.backup_toast_import_decryption_failed);
|
return BackupTaskResult.failure(BackupTaskResult.ResultType.RESTORE, R.string.backup_toast_import_decryption_failed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,14 @@ import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||||
import org.shadowice.flocke.andotp.Utilities.Settings;
|
import org.shadowice.flocke.andotp.Utilities.Settings;
|
||||||
import org.shadowice.flocke.andotp.Utilities.StorageAccessHelper;
|
import org.shadowice.flocke.andotp.Utilities.StorageAccessHelper;
|
||||||
|
|
||||||
public abstract class GenericBackupTask extends UiBasedBackgroundTask<GenericBackupTask.BackupTaskResult> {
|
public abstract class GenericBackupTask extends UiBasedBackgroundTask<BackupTaskResult> {
|
||||||
protected final Context applicationContext;
|
protected final Context applicationContext;
|
||||||
protected final Settings settings;
|
protected final Settings settings;
|
||||||
protected final Constants.BackupType type;
|
protected final Constants.BackupType type;
|
||||||
protected Uri uri;
|
protected Uri uri;
|
||||||
|
|
||||||
public GenericBackupTask(Context context, @Nullable Uri uri) {
|
public GenericBackupTask(Context context, @Nullable Uri uri) {
|
||||||
super(BackupTaskResult.failure());
|
super(BackupTaskResult.failure(BackupTaskResult.ResultType.BACKUP, R.string.backup_toast_export_failed));
|
||||||
|
|
||||||
this.applicationContext = context.getApplicationContext();
|
this.applicationContext = context.getApplicationContext();
|
||||||
this.settings = new Settings(applicationContext);
|
this.settings = new Settings(applicationContext);
|
||||||
|
@ -37,7 +37,7 @@ public abstract class GenericBackupTask extends UiBasedBackgroundTask<GenericBac
|
||||||
BackupHelper.BackupFile backupFile = BackupHelper.backupFile(applicationContext, settings.getBackupLocation(), type);
|
BackupHelper.BackupFile backupFile = BackupHelper.backupFile(applicationContext, settings.getBackupLocation(), type);
|
||||||
|
|
||||||
if (backupFile.file == null)
|
if (backupFile.file == null)
|
||||||
return new BackupTaskResult(false, backupFile.errorMessage, null);
|
return new BackupTaskResult(BackupTaskResult.ResultType.BACKUP,false, null, backupFile.errorMessage);
|
||||||
|
|
||||||
uri = backupFile.file.getUri();
|
uri = backupFile.file.getUri();
|
||||||
fileName = backupFile.file.getName();
|
fileName = backupFile.file.getName();
|
||||||
|
@ -48,33 +48,12 @@ public abstract class GenericBackupTask extends UiBasedBackgroundTask<GenericBac
|
||||||
boolean success = doBackup();
|
boolean success = doBackup();
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
return BackupTaskResult.success(fileName);
|
return BackupTaskResult.success(BackupTaskResult.ResultType.BACKUP ,fileName);
|
||||||
else
|
else
|
||||||
return BackupTaskResult.failure();
|
return BackupTaskResult.failure(BackupTaskResult.ResultType.BACKUP, R.string.backup_toast_export_failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
protected abstract Constants.BackupType getBackupType();
|
protected abstract Constants.BackupType getBackupType();
|
||||||
protected abstract boolean doBackup();
|
protected abstract boolean doBackup();
|
||||||
|
|
||||||
|
|
||||||
public static class BackupTaskResult {
|
|
||||||
public final boolean success;
|
|
||||||
public final int messageId;
|
|
||||||
public final String fileName;
|
|
||||||
|
|
||||||
public BackupTaskResult(boolean success, int messageId, String fileName) {
|
|
||||||
this.success = success;
|
|
||||||
this.messageId = messageId;
|
|
||||||
this.fileName = fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BackupTaskResult success(String fileName) {
|
|
||||||
return new BackupTaskResult(true, R.string.backup_toast_export_success, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BackupTaskResult failure() {
|
|
||||||
return new BackupTaskResult(false, R.string.backup_toast_export_failed, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package org.shadowice.flocke.andotp.Tasks;
|
package org.shadowice.flocke.andotp.Tasks;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -10,13 +9,13 @@ import androidx.annotation.Nullable;
|
||||||
import org.shadowice.flocke.andotp.R;
|
import org.shadowice.flocke.andotp.R;
|
||||||
import org.shadowice.flocke.andotp.Utilities.Settings;
|
import org.shadowice.flocke.andotp.Utilities.Settings;
|
||||||
|
|
||||||
public abstract class GenericRestoreTask extends UiBasedBackgroundTask<GenericRestoreTask.RestoreTaskResult> {
|
public abstract class GenericRestoreTask extends UiBasedBackgroundTask<BackupTaskResult> {
|
||||||
protected final Context applicationContext;
|
protected final Context applicationContext;
|
||||||
protected final Settings settings;
|
protected final Settings settings;
|
||||||
protected Uri uri;
|
protected Uri uri;
|
||||||
|
|
||||||
public GenericRestoreTask(Context context, @Nullable Uri uri) {
|
public GenericRestoreTask(Context context, @Nullable Uri uri) {
|
||||||
super(GenericRestoreTask.RestoreTaskResult.failure(R.string.backup_toast_import_failed));
|
super(BackupTaskResult.failure(BackupTaskResult.ResultType.RESTORE, R.string.backup_toast_import_failed));
|
||||||
|
|
||||||
this.applicationContext = context.getApplicationContext();
|
this.applicationContext = context.getApplicationContext();
|
||||||
this.settings = new Settings(applicationContext);
|
this.settings = new Settings(applicationContext);
|
||||||
|
@ -26,38 +25,5 @@ public abstract class GenericRestoreTask extends UiBasedBackgroundTask<GenericRe
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
protected abstract RestoreTaskResult doInBackground();
|
protected abstract BackupTaskResult doInBackground();
|
||||||
|
|
||||||
public static class RestoreTaskResult {
|
|
||||||
public final boolean success;
|
|
||||||
public final String payload;
|
|
||||||
public final int messageId;
|
|
||||||
|
|
||||||
public boolean isPGP = false;
|
|
||||||
public Intent decryptIntent = null;
|
|
||||||
public Uri uri = null;
|
|
||||||
|
|
||||||
public RestoreTaskResult(boolean success, String payload, int messageId) {
|
|
||||||
this.success = success;
|
|
||||||
this.payload = payload;
|
|
||||||
this.messageId = messageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestoreTaskResult(boolean success, String payload, int messageId, boolean isPGP, Intent decryptIntent, Uri uri) {
|
|
||||||
this.success = success;
|
|
||||||
this.payload = payload;
|
|
||||||
this.messageId = messageId;
|
|
||||||
this.isPGP = isPGP;
|
|
||||||
this.decryptIntent = decryptIntent;
|
|
||||||
this.uri = uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RestoreTaskResult success(String payload) {
|
|
||||||
return new RestoreTaskResult(true, payload, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RestoreTaskResult failure(int messageId) {
|
|
||||||
return new RestoreTaskResult(false, null, messageId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ public class PGPRestoreTask extends GenericRestoreTask {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
protected RestoreTaskResult doInBackground() {
|
protected BackupTaskResult doInBackground() {
|
||||||
String data = StorageAccessHelper.loadFileString(applicationContext, uri);
|
String data = StorageAccessHelper.loadFileString(applicationContext, uri);
|
||||||
|
|
||||||
return new RestoreTaskResult(true, data, 0, true, decryptIntent, uri);
|
return new BackupTaskResult(BackupTaskResult.ResultType.RESTORE,true, data, 0, true, decryptIntent, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ public class PlainTextRestoreTask extends GenericRestoreTask {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
protected RestoreTaskResult doInBackground() {
|
protected BackupTaskResult doInBackground() {
|
||||||
String data = StorageAccessHelper.loadFileString(applicationContext, uri);
|
String data = StorageAccessHelper.loadFileString(applicationContext, uri);
|
||||||
return RestoreTaskResult.success(data);
|
return BackupTaskResult.success(BackupTaskResult.ResultType.RESTORE, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ public abstract class UiBasedBackgroundTask<Result> {
|
||||||
private Result awaitedResult;
|
private Result awaitedResult;
|
||||||
|
|
||||||
private volatile boolean isCanceled = false;
|
private volatile boolean isCanceled = false;
|
||||||
private volatile boolean isRunning = false;
|
|
||||||
|
|
||||||
/** @param failedResult The result to return if the task fails (throws an exception or returns null). */
|
/** @param failedResult The result to return if the task fails (throws an exception or returns null). */
|
||||||
public UiBasedBackgroundTask(@NonNull Result failedResult) {
|
public UiBasedBackgroundTask(@NonNull Result failedResult) {
|
||||||
|
@ -53,10 +52,7 @@ public abstract class UiBasedBackgroundTask<Result> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void emitResultOnMainThread(@NonNull UiCallback<Result> callback, @NonNull Result result) {
|
private void emitResultOnMainThread(@NonNull UiCallback<Result> callback, @NonNull Result result) {
|
||||||
mainThreadHandler.post(() -> {
|
mainThreadHandler.post(() -> callback.onResult(result));
|
||||||
callback.onResult(result);
|
|
||||||
isRunning = false;
|
|
||||||
});
|
|
||||||
this.callback = null;
|
this.callback = null;
|
||||||
this.awaitedResult = null;
|
this.awaitedResult = null;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +60,6 @@ public abstract class UiBasedBackgroundTask<Result> {
|
||||||
/** Executed the task on a background thread. Safe to call from the main thread. */
|
/** Executed the task on a background thread. Safe to call from the main thread. */
|
||||||
@AnyThread
|
@AnyThread
|
||||||
public void execute() {
|
public void execute() {
|
||||||
isRunning = true;
|
|
||||||
executor.execute(this::runTask);
|
executor.execute(this::runTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,15 +96,9 @@ public abstract class UiBasedBackgroundTask<Result> {
|
||||||
return isCanceled;
|
return isCanceled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@AnyThread
|
|
||||||
public boolean isRunning() {
|
|
||||||
return isRunning;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AnyThread
|
@AnyThread
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
isCanceled = true;
|
isCanceled = true;
|
||||||
isRunning = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
|
|
@ -63,8 +63,8 @@ import org.shadowice.flocke.andotp.Database.Entry;
|
||||||
import org.shadowice.flocke.andotp.Database.EntryList;
|
import org.shadowice.flocke.andotp.Database.EntryList;
|
||||||
import org.shadowice.flocke.andotp.Dialogs.ManualEntryDialog;
|
import org.shadowice.flocke.andotp.Dialogs.ManualEntryDialog;
|
||||||
import org.shadowice.flocke.andotp.R;
|
import org.shadowice.flocke.andotp.R;
|
||||||
|
import org.shadowice.flocke.andotp.Tasks.BackupTaskResult;
|
||||||
import org.shadowice.flocke.andotp.Tasks.EncryptedBackupTask;
|
import org.shadowice.flocke.andotp.Tasks.EncryptedBackupTask;
|
||||||
import org.shadowice.flocke.andotp.Tasks.GenericBackupTask;
|
|
||||||
import org.shadowice.flocke.andotp.Utilities.BackupHelper;
|
import org.shadowice.flocke.andotp.Utilities.BackupHelper;
|
||||||
import org.shadowice.flocke.andotp.Utilities.Constants;
|
import org.shadowice.flocke.andotp.Utilities.Constants;
|
||||||
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
import org.shadowice.flocke.andotp.Utilities.DatabaseHelper;
|
||||||
|
@ -198,7 +198,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleTaskResult(GenericBackupTask.BackupTaskResult result) {
|
private void handleTaskResult(BackupTaskResult result) {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
Toast.makeText(context, R.string.backup_toast_export_success, Toast.LENGTH_LONG).show();
|
Toast.makeText(context, R.string.backup_toast_export_success, Toast.LENGTH_LONG).show();
|
||||||
} else {
|
} else {
|
||||||
|
@ -270,9 +270,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
||||||
|
|
||||||
Constants.CardLayouts layout = settings.getCardLayout();
|
Constants.CardLayouts layout = settings.getCardLayout();
|
||||||
|
|
||||||
if (layout == Constants.CardLayouts.DEFAULT) {
|
if (layout == Constants.CardLayouts.COMPACT) {
|
||||||
cardLayout = R.layout.component_card_default;
|
|
||||||
} else if (layout == Constants.CardLayouts.COMPACT) {
|
|
||||||
cardLayout = R.layout.component_card_compact;
|
cardLayout = R.layout.component_card_compact;
|
||||||
} else if (layout == Constants.CardLayouts.FULL) {
|
} else if (layout == Constants.CardLayouts.FULL) {
|
||||||
cardLayout = R.layout.component_card_full;
|
cardLayout = R.layout.component_card_full;
|
||||||
|
@ -371,7 +369,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
||||||
private void copyHandler(final int position, final String text, final boolean dropToBackground) {
|
private void copyHandler(final int position, final String text, final boolean dropToBackground) {
|
||||||
Tools.copyToClipboard(context, text);
|
Tools.copyToClipboard(context, text);
|
||||||
updateLastUsedAndFrequency(position, getRealIndex(position));
|
updateLastUsedAndFrequency(position, getRealIndex(position));
|
||||||
if(context != null && dropToBackground) {
|
if (dropToBackground) {
|
||||||
((MainActivity)context).moveTaskToBack(true);
|
((MainActivity)context).moveTaskToBack(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue