diff --git a/briar-android/src/main/AndroidManifest.xml b/briar-android/src/main/AndroidManifest.xml
index 3452e6873..76f00e6c4 100644
--- a/briar-android/src/main/AndroidManifest.xml
+++ b/briar-android/src/main/AndroidManifest.xml
@@ -499,6 +499,15 @@
android:value="org.briarproject.briar.android.conversation.ConversationActivity" />
+
+
+
+
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
index 178df5d3d..2c88bbf79 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
@@ -73,6 +73,9 @@ import org.briarproject.briar.android.remotewipe.WiperSelectorFragment;
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeActivity;
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeExplainerFragment;
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeSuccessFragment;
+import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeActivity;
+import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeState;
+import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeSuccessFragment;
import org.briarproject.briar.android.reporting.CrashFragment;
import org.briarproject.briar.android.reporting.CrashReportActivity;
import org.briarproject.briar.android.reporting.ReportFormFragment;
@@ -229,6 +232,8 @@ public interface ActivityComponent {
void inject(RemoteWipeActivatedActivity remoteWipeActivatedActivity);
+ void inject(RevokeRemoteWipeActivity revokeRemoteWipeActivity);
+
// Fragments
void inject(AuthorNameFragment fragment);
@@ -330,4 +335,6 @@ public interface ActivityComponent {
void inject(ActivateRemoteWipeExplainerFragment activateRemoteWipeExplainerFragment);
void inject(ActivateRemoteWipeSuccessFragment activateRemoteWipeSuccessFragment);
+
+ void inject(RevokeRemoteWipeSuccessFragment revokeRemoteWipeSuccessFragment);
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java
index c7f3a6385..c43c91b7a 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java
@@ -53,6 +53,7 @@ import org.briarproject.briar.android.forum.ForumActivity;
import org.briarproject.briar.android.introduction.IntroductionActivity;
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeActivity;
+import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeActivity;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardActivity;
import org.briarproject.briar.android.util.BriarSnackbarBuilder;
import org.briarproject.briar.android.view.BriarRecyclerView;
@@ -379,6 +380,13 @@ public class ConversationActivity extends BriarActivity
}
});
+ // enable revoke remote wipe action if available
+ observeOnce(viewModel.isRemoteWiper(), this, isWiper -> {
+ if (isWiper != null && isWiper) {
+ menu.findItem(R.id.action_revoke_remote_wipe).setEnabled(true);
+ }
+ });
+
return super.onCreateOptionsMenu(menu);
}
@@ -417,6 +425,12 @@ public class ConversationActivity extends BriarActivity
r.putExtra(CONTACT_ID, contactId.getInt());
startActivity(r);
return true;
+ case R.id.action_revoke_remote_wipe:
+ if (contactId == null) return false;
+ Intent s = new Intent(this, RevokeRemoteWipeActivity.class);
+ s.putExtra(CONTACT_ID, contactId.getInt());
+ startActivity(s);
+ return true;
default:
return super.onOptionsItemSelected(item);
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java
index c90c789d6..398799980 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java
@@ -107,6 +107,7 @@ public class ConversationViewModel extends DbViewModel
private final MutableLiveEvent addedHeader =
new MutableLiveEvent<>();
private final MutableLiveData amRemoteWiper = new MutableLiveData<>();
+ private final MutableLiveData isRemoteWiper = new MutableLiveData<>();
@Inject
ConversationViewModel(Application application,
@@ -306,6 +307,10 @@ public class ConversationViewModel extends DbViewModel
boolean amWiper = db.transactionWithResult(true,
txn -> remoteWipeManager.amWiper(txn, c));
amRemoteWiper.postValue(amWiper);
+
+ boolean isWiper = db.transactionWithResult(true,
+ txn -> remoteWipeManager.isWiper(txn, c));
+ isRemoteWiper.postValue(isWiper);
}
@DatabaseExecutor
@@ -395,6 +400,10 @@ public class ConversationViewModel extends DbViewModel
return amRemoteWiper;
}
+ LiveData isRemoteWiper() {
+ return isRemoteWiper;
+ }
+
@UiThread
void recheckFeaturesAndOnboarding(ContactId contactId) {
runOnDbThread(() -> {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/activate/ActivateRemoteWipeSuccessFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/activate/ActivateRemoteWipeSuccessFragment.java
index d5d3ad343..8daec0124 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/activate/ActivateRemoteWipeSuccessFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/activate/ActivateRemoteWipeSuccessFragment.java
@@ -9,6 +9,7 @@ import android.widget.Button;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
+import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeViewModel;
import javax.inject.Inject;
@@ -24,13 +25,13 @@ public class ActivateRemoteWipeSuccessFragment extends BaseFragment {
@Inject
ViewModelProvider.Factory viewModelFactory;
- private ActivateRemoteWipeViewModel viewModel;
+ private RevokeRemoteWipeViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
- .get(ActivateRemoteWipeViewModel.class);
+ .get(RevokeRemoteWipeViewModel.class);
}
@Nullable
@@ -38,6 +39,7 @@ public class ActivateRemoteWipeSuccessFragment extends BaseFragment {
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
+ // TODO change layout
View view = inflater.inflate(R.layout.fragment_activate_remote_wipe_success,
container, false);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeActivity.java
new file mode 100644
index 000000000..819b88f41
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeActivity.java
@@ -0,0 +1,67 @@
+package org.briarproject.briar.android.remotewipe.revoke;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.Toast;
+
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.fragment.BaseFragment;
+
+import javax.inject.Inject;
+
+import androidx.lifecycle.ViewModelProvider;
+
+import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
+
+public class RevokeRemoteWipeActivity extends BriarActivity implements
+ BaseFragment.BaseFragmentListener {
+
+ @Inject
+ ViewModelProvider.Factory viewModelFactory;
+ RevokeRemoteWipeViewModel viewModel;
+
+ @Override
+ public void injectActivity(ActivityComponent component) {
+ component.inject(this);
+
+ viewModel = new ViewModelProvider(this, viewModelFactory)
+ .get(RevokeRemoteWipeViewModel.class);
+
+ viewModel.getState().observe(this, this::onStateChanged);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_distributed_backup);
+
+ if (savedInstanceState == null) {
+ Intent intent = getIntent();
+ int id = intent.getIntExtra(CONTACT_ID, -1);
+ if (id == -1) throw new IllegalStateException("No ContactId");
+ ContactId contactId = new ContactId(id);
+ viewModel.revokeRemoteWipeStatus(contactId);
+// showInitialFragment(new ActivateRemoteWipeExplainerFragment());
+ }
+ }
+
+ private void onStateChanged(RevokeRemoteWipeState state) {
+ switch(state) {
+ case FAILED:
+ // TODO change text
+ Toast.makeText(this,
+ R.string.remote_wipe_activate_failure,
+ Toast.LENGTH_LONG).show();
+ break;
+ case SUCCESS:
+ showNextFragment(new RevokeRemoteWipeSuccessFragment());
+ break;
+ default: // FINISHED or CANCELLED
+ finish();
+ break;
+ }
+ }
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeState.java b/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeState.java
new file mode 100644
index 000000000..f18fe2e84
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeState.java
@@ -0,0 +1,7 @@
+package org.briarproject.briar.android.remotewipe.revoke;
+
+public enum RevokeRemoteWipeState {
+ FAILED,
+ SUCCESS,
+ FINISHED
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeSuccessFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeSuccessFragment.java
new file mode 100644
index 000000000..666bc7ea9
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeSuccessFragment.java
@@ -0,0 +1,55 @@
+package org.briarproject.briar.android.remotewipe.revoke;
+
+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 org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeSuccessFragment;
+import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeViewModel;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.ViewModelProvider;
+
+public class RevokeRemoteWipeSuccessFragment extends BaseFragment {
+
+ public static final String TAG =
+ ActivateRemoteWipeSuccessFragment.class.getName();
+
+ @Inject
+ ViewModelProvider.Factory viewModelFactory;
+
+ private ActivateRemoteWipeViewModel viewModel;
+
+ @Override
+ public void injectFragment(ActivityComponent component) {
+ component.inject(this);
+ viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
+ .get(ActivateRemoteWipeViewModel.class);
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_activate_remote_wipe_success,
+ container, false);
+
+ Button button = view.findViewById(R.id.button);
+ button.setOnClickListener(e -> viewModel.onSuccessDismissed());
+ return view;
+ }
+
+ @Override
+ public String getUniqueTag() {
+ return TAG;
+ }
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeViewModel.java
new file mode 100644
index 000000000..31f6d4cf2
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/remotewipe/revoke/RevokeRemoteWipeViewModel.java
@@ -0,0 +1,60 @@
+package org.briarproject.briar.android.remotewipe.revoke;
+
+import android.app.Application;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeState;
+import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
+
+import javax.inject.Inject;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.MutableLiveData;
+
+public class RevokeRemoteWipeViewModel extends AndroidViewModel {
+
+ private final RemoteWipeManager remoteWipeManager;
+ private final DatabaseComponent db;
+ private final MutableLiveData state = new MutableLiveData<>();
+ private ContactId contactId;
+
+ @Inject
+ public RevokeRemoteWipeViewModel(
+ @NonNull Application application,
+ RemoteWipeManager remoteWipeManager,
+ DatabaseComponent db) {
+ super(application);
+ this.remoteWipeManager = remoteWipeManager;
+ this.db = db;
+ }
+
+ public MutableLiveData getState() {
+ return state;
+ }
+
+ public void revokeRemoteWipeStatus(ContactId c) {
+ contactId = c;
+ try {
+ db.transaction(false, txn -> {
+ remoteWipeManager.revoke(txn, contactId);
+ });
+ } catch (DbException e) {
+ state.postValue(RevokeRemoteWipeState.FAILED);
+ } catch (FormatException e) {
+ state.postValue(RevokeRemoteWipeState.FAILED);
+ }
+ state.postValue(RevokeRemoteWipeState.SUCCESS);
+ }
+
+ public void onCancelClicked() {
+// state.postValue(ActivateRemoteWipeState.CANCELLED);
+ }
+
+ public void onSuccessDismissed() {
+ state.postValue(RevokeRemoteWipeState.FINISHED);
+ }
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/CustodianStatusAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/CustodianStatusAdapter.java
new file mode 100644
index 000000000..0e6922aea
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/CustodianStatusAdapter.java
@@ -0,0 +1,27 @@
+package org.briarproject.briar.android.socialbackup;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.contact.BaseContactListAdapter;
+import org.briarproject.briar.android.contact.ContactItem;
+import org.briarproject.briar.android.contact.ContactItemViewHolder;
+
+public class CustodianStatusAdapter extends BaseContactListAdapter> {
+
+ CustodianStatusAdapter(Context context) {
+ super(context, ContactItem.class, null);
+ }
+
+ @Override
+ public ContactItemViewHolder onCreateViewHolder(
+ ViewGroup viewGroup, int i) {
+ View v = LayoutInflater.from(viewGroup.getContext()).inflate(
+ R.layout.list_item_contact_small, viewGroup, false);
+ return new ContactItemViewHolder<>(v);
+ }
+
+}
diff --git a/briar-android/src/main/res/menu/conversation_actions.xml b/briar-android/src/main/res/menu/conversation_actions.xml
index 589564aa1..5c699cac1 100644
--- a/briar-android/src/main/res/menu/conversation_actions.xml
+++ b/briar-android/src/main/res/menu/conversation_actions.xml
@@ -39,4 +39,11 @@
android:title="@string/activate_remote_wipe"
android:enabled="false"
app:showAsAction="never"/>
+
+
\ No newline at end of file
diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml
index 30f5feaee..3a3c9aed1 100644
--- a/briar-android/src/main/res/values/strings.xml
+++ b/briar-android/src/main/res/values/strings.xml
@@ -760,5 +760,9 @@
Activate a remote wipe of this contact\'s device
If confirmed by a second contact, sending this signal will remove all briar contacts and messages from this contact\s device.
+
+ Revoke Remote Wipe
+ Revoke remote wipe status
+
Ok