Add view model for setup process, add setup explainer fragment

This commit is contained in:
ameba23
2022-02-02 10:30:50 +01:00
parent 01fd193686
commit 43e8d06493
9 changed files with 252 additions and 65 deletions

View File

@@ -80,6 +80,7 @@ import org.briarproject.briar.android.sharing.ShareBlogFragment;
import org.briarproject.briar.android.sharing.ShareForumActivity;
import org.briarproject.briar.android.sharing.ShareForumFragment;
import org.briarproject.briar.android.sharing.SharingModule;
import org.briarproject.briar.android.socialbackup.SetupExplainerFragment;
import org.briarproject.briar.android.socialbackup.recover.CustodianRecoveryModeExplainerFragment;
import org.briarproject.briar.android.socialbackup.CustodianSelectorFragment;
import org.briarproject.briar.android.socialbackup.DistributedBackupActivity;
@@ -306,4 +307,6 @@ public interface ActivityComponent {
void inject(OwnerRecoveryModeErrorFragment ownerRecoveryModeErrorFragment);
void inject(CustodianReturnShardErrorFragment custodianReturnShardErrorFragment);
void inject(SetupExplainerFragment setupExplainerFragment);
}

View File

@@ -23,6 +23,7 @@ import java.util.Collection;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import static java.util.Objects.requireNonNull;
@@ -32,6 +33,18 @@ public class CustodianSelectorFragment extends ContactSelectorFragment {
public static final String TAG = CustodianSelectorFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private SocialBackupSetupViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(SocialBackupSetupViewModel.class);
}
@Inject
CreateBackupController controller;
@@ -44,11 +57,6 @@ public class CustodianSelectorFragment extends ContactSelectorFragment {
return fragment;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

View File

@@ -12,7 +12,9 @@ import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.contactselection.ContactSelectorListener;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardViewModel;
import org.briarproject.briar.api.socialbackup.BackupMetadata;
import org.briarproject.briar.api.socialbackup.SocialBackup;
import org.briarproject.briar.api.socialbackup.SocialBackupManager;
import java.util.Collection;
@@ -20,25 +22,22 @@ import java.util.List;
import javax.inject.Inject;
import androidx.lifecycle.ViewModelProvider;
public class DistributedBackupActivity extends BriarActivity implements
BaseFragment.BaseFragmentListener, ContactSelectorListener,
ThresholdDefinedListener,
ShardsSentFragment.ShardsSentDismissedListener {
private Collection<ContactId> custodians;
private SocialBackupSetupViewModel viewModel;
@Inject
public SocialBackupManager socialBackupManager;
@Inject
public ContactManager contactManager;
@Inject
public DatabaseComponent db;
ViewModelProvider.Factory viewModelFactory;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(this, viewModelFactory)
.get(SocialBackupSetupViewModel.class);
}
@Override
@@ -46,19 +45,13 @@ public class DistributedBackupActivity extends BriarActivity implements
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_distributed_backup);
try {
db.transaction(false, txn -> {
BackupMetadata backupMetadata =
socialBackupManager.getBackupMetadata(txn);
if (backupMetadata == null) throw new DbException();
ExistingBackupFragment fragment =
ExistingBackupFragment.newInstance(backupMetadata);
showInitialFragment(fragment);
});
} catch (DbException e) {
// Check the number of contacts in the contacts list > 1
if (viewModel.haveExistingBackup()) {
ExistingBackupFragment fragment =
ExistingBackupFragment.newInstance();
showInitialFragment(fragment);
} else {
try {
if (contactManager.getContacts().size() < 2) {
if (!viewModel.haveEnoughContacts()) {
Toast.makeText(this,
R.string.social_backup_not_enough_contacts,
Toast.LENGTH_LONG).show();
@@ -70,9 +63,32 @@ public class DistributedBackupActivity extends BriarActivity implements
Toast.LENGTH_LONG).show();
finish();
}
CustodianSelectorFragment fragment =
CustodianSelectorFragment.newInstance();
showInitialFragment(fragment);
showInitialFragment(new SetupExplainerFragment());
}
viewModel.getState()
.observe(this, this::onStateChanged);
}
private void onStateChanged(SocialBackupSetupViewModel.State state) {
switch(state) {
case SUCCESS:
try {
viewModel.createBackup();
ShardsSentFragment fragment = new ShardsSentFragment();
showNextFragment(fragment);
} catch (DbException e) {
Toast.makeText(this,
"There was an error when creating the backup",
Toast.LENGTH_LONG).show();
finish();
}
break;
case CHOOSING_CUSTODIANS:
CustodianSelectorFragment fragment =
CustodianSelectorFragment.newInstance();
showNextFragment(fragment);
break;
}
}
@@ -81,32 +97,15 @@ public class DistributedBackupActivity extends BriarActivity implements
Toast.makeText(this,
String.format("Selected %d contacts", contacts.size()),
Toast.LENGTH_SHORT).show();
custodians = contacts;
viewModel.setCustodians(contacts);
ThresholdSelectorFragment fragment =
ThresholdSelectorFragment.newInstance(contacts.size());
showNextFragment(fragment);
}
@Override
public void thresholdDefined(int threshold) {
try {
db.transaction(false, txn -> {
socialBackupManager
.createBackup(txn, (List<ContactId>) custodians,
threshold);
ShardsSentFragment fragment = new ShardsSentFragment();
showNextFragment(fragment);
});
} catch (DbException e) {
Toast.makeText(this,
"There was an error when creating the backup",
Toast.LENGTH_LONG).show();
finish();
}
}
@Override
public void shardsSentDismissed() {
finish();
}
}

View File

@@ -16,8 +16,11 @@ import org.briarproject.briar.api.socialbackup.BackupMetadata;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
public class ExistingBackupFragment extends BaseFragment {
@@ -25,9 +28,21 @@ public class ExistingBackupFragment extends BaseFragment {
private static final String CUSTODIANS = "custodians";
public static final String TAG = ExistingBackupFragment.class.getName();
public static ExistingBackupFragment newInstance(
BackupMetadata backupMetadata) {
@Inject
ViewModelProvider.Factory viewModelFactory;
private static SocialBackupSetupViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(SocialBackupSetupViewModel.class);
}
public static ExistingBackupFragment newInstance() {
Bundle bundle = new Bundle();
BackupMetadata backupMetadata = viewModel.getBackupMetadata();
List<Author> custodians = backupMetadata.getCustodians();
ArrayList custodianNames = new ArrayList();
for (Author custodian : custodians) {
@@ -85,9 +100,5 @@ public class ExistingBackupFragment extends BaseFragment {
return TAG;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
}

View File

@@ -0,0 +1,54 @@
package org.briarproject.briar.android.socialbackup;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
public class SetupExplainerFragment extends BaseFragment {
public static final String TAG =
SetupExplainerFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private SocialBackupSetupViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(SocialBackupSetupViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable
ViewGroup container, @Nullable Bundle savedInstanceState) {
View view =
inflater.inflate(R.layout.fragment_social_backup_setup_explainer,
container, false);
Button button = view.findViewById(R.id.button);
button.setOnClickListener(e -> viewModel.onExplainerDismissed());
return view;
}
@Override
public String getUniqueTag() {
return TAG;
}
}

View File

@@ -0,0 +1,100 @@
package org.briarproject.briar.android.socialbackup;
import android.app.Application;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.briar.api.socialbackup.BackupMetadata;
import org.briarproject.briar.api.socialbackup.SocialBackupManager;
import java.util.Collection;
import java.util.List;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.MutableLiveData;
public class SocialBackupSetupViewModel extends AndroidViewModel {
private final SocialBackupManager socialBackupManager;
private final DatabaseComponent db;
private final ContactManager contactManager;
private BackupMetadata backupMetadata;
private Collection<ContactId> custodians;
private int threshold;
public enum State {
EXPLAINING,
CHOOSING_CUSTODIANS,
GETTING_THRESHOLD,
SUCCESS
}
private final MutableLiveData<State> state =
new MutableLiveData<>();
@Inject
public SocialBackupSetupViewModel(
@NonNull Application app,
DatabaseComponent db,
SocialBackupManager socialBackupManager,
ContactManager contactManager
) {
super(app);
this.socialBackupManager = socialBackupManager;
this.db = db;
this.contactManager = contactManager;
}
public boolean haveExistingBackup() {
try {
db.transaction(false, txn -> {
backupMetadata =
socialBackupManager.getBackupMetadata(txn);
if (backupMetadata == null) throw new DbException();
});
} catch (DbException e) {
return false;
}
return true;
}
public BackupMetadata getBackupMetadata() {
return backupMetadata;
}
public boolean haveEnoughContacts() throws DbException {
return (contactManager.getContacts().size() > 1);
}
public void setCustodians(Collection<ContactId> contacts) {
custodians = contacts;
}
public void createBackup() throws DbException {
db.transaction(false, txn -> {
socialBackupManager
.createBackup(txn, (List<ContactId>) custodians,
threshold);
});
}
public void setThreshold(int threshold) {
this.threshold = threshold;
state.postValue(State.SUCCESS);
}
public MutableLiveData<State> getState() {
return state;
}
public void onExplainerDismissed() {
state.postValue(State.CHOOSING_CUSTODIANS);
}
}

View File

@@ -17,8 +17,11 @@ import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.magmacollective.darkcrystal.secretsharingwrapper.SecretSharingWrapper;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
public class ThresholdSelectorFragment extends BaseFragment {
@@ -35,6 +38,18 @@ public class ThresholdSelectorFragment extends BaseFragment {
private TextView message;
private TextView mOfn;
@Inject
ViewModelProvider.Factory viewModelFactory;
private SocialBackupSetupViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(SocialBackupSetupViewModel.class);
}
public static ThresholdSelectorFragment newInstance(int numberCustodians) {
Bundle bundle = new Bundle();
bundle.putInt(NUMBER_CUSTODIANS, numberCustodians);
@@ -103,11 +118,6 @@ public class ThresholdSelectorFragment extends BaseFragment {
return TAG;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.define_threshold_actions, menu);
@@ -118,11 +128,7 @@ public class ThresholdSelectorFragment extends BaseFragment {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_threshold_defined:
try {
listener.thresholdDefined(threshold);
} catch (DbException e) {
e.printStackTrace();
}
viewModel.setThreshold(threshold);
return true;
default:
return super.onOptionsItemSelected(item);

View File

@@ -53,7 +53,7 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
final QrCodeDecoder qrCodeDecoder;
private boolean qrCodeRead = false;
private WifiManager wifiManager;
private final MutableLiveEvent<Boolean > continueClicked = new MutableLiveEvent<>();
private final MutableLiveEvent<Boolean> continueClicked = new MutableLiveEvent<>();
private final MutableLiveEvent<Boolean> showCameraFragment =
new MutableLiveEvent<>();
private final MutableLiveEvent<Boolean> successDismissed =

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>