Merge activities for adding contact nearby

and rename related classes to consolidate names
This commit is contained in:
Torsten Grote
2021-02-04 14:31:41 -03:00
parent 700f6e05bf
commit bcc0442add
14 changed files with 245 additions and 276 deletions

View File

@@ -342,7 +342,7 @@
</activity>
<activity
android:name="org.briarproject.briar.android.contact.add.nearby.ContactExchangeActivity"
android:name="org.briarproject.briar.android.contact.add.nearby.AddNearbyContactActivity"
android:label="@string/add_contact_title"
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
android:theme="@style/BriarTheme.NoActionBar">

View File

@@ -31,7 +31,7 @@ import org.briarproject.briar.android.account.DozeHelperModule;
import org.briarproject.briar.android.account.LockManagerImpl;
import org.briarproject.briar.android.account.SetupModule;
import org.briarproject.briar.android.contact.ContactListModule;
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeModule;
import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactModule;
import org.briarproject.briar.android.forum.ForumModule;
import org.briarproject.briar.android.introduction.IntroductionModule;
import org.briarproject.briar.android.logging.LoggingModule;
@@ -75,7 +75,7 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
@Module(includes = {
SetupModule.class,
DozeHelperModule.class,
ContactExchangeModule.class,
AddNearbyContactModule.class,
LoggingModule.class,
LoginModule.class,
NavDrawerModule.class,

View File

@@ -21,11 +21,10 @@ import org.briarproject.briar.android.blog.RssFeedImportActivity;
import org.briarproject.briar.android.blog.RssFeedManageActivity;
import org.briarproject.briar.android.blog.WriteBlogPostActivity;
import org.briarproject.briar.android.contact.ContactListFragment;
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeActivity;
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeErrorFragment;
import org.briarproject.briar.android.contact.add.nearby.IntroFragment;
import org.briarproject.briar.android.contact.add.nearby.KeyAgreementActivity;
import org.briarproject.briar.android.contact.add.nearby.KeyAgreementFragment;
import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactActivity;
import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactErrorFragment;
import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactFragment;
import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactIntroFragment;
import org.briarproject.briar.android.contact.add.remote.AddContactActivity;
import org.briarproject.briar.android.contact.add.remote.LinkExchangeFragment;
import org.briarproject.briar.android.contact.add.remote.NicknameFragment;
@@ -109,9 +108,7 @@ public interface ActivityComponent {
void inject(PanicPreferencesActivity activity);
void inject(ContactExchangeActivity activity);
void inject(KeyAgreementActivity activity);
void inject(AddNearbyContactActivity activity);
void inject(ConversationActivity activity);
@@ -209,9 +206,9 @@ public interface ActivityComponent {
void inject(FeedFragment fragment);
void inject(IntroFragment fragment);
void inject(KeyAgreementFragment fragment);
void inject(AddNearbyContactIntroFragment fragment);
void inject(AddNearbyContactFragment fragment);
void inject(LinkExchangeFragment fragment);
@@ -229,7 +226,7 @@ public interface ActivityComponent {
void inject(ScreenFilterDialogFragment fragment);
void inject(ContactExchangeErrorFragment fragment);
void inject(AddNearbyContactErrorFragment fragment);
void inject(AliasDialogFragment aliasDialogFragment);

View File

@@ -15,11 +15,11 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactActivity;
import org.briarproject.briar.android.contact.add.remote.AddContactActivity;
import org.briarproject.briar.android.contact.add.remote.PendingContactListActivity;
import org.briarproject.briar.android.conversation.ConversationActivity;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeActivity;
import org.briarproject.briar.android.util.BriarSnackbarBuilder;
import org.briarproject.briar.android.view.BriarRecyclerView;
@@ -125,7 +125,8 @@ public class ContactListFragment extends BaseFragment
switch (itemId) {
case R.id.action_add_contact_nearby:
Intent intent =
new Intent(getContext(), ContactExchangeActivity.class);
new Intent(getContext(),
AddNearbyContactActivity.class);
startActivity(intent);
return;
case R.id.action_add_contact_remotely:

View File

@@ -0,0 +1,76 @@
package org.briarproject.briar.android.contact.add.nearby;
import android.graphics.Bitmap;
import org.briarproject.bramble.api.identity.Author;
import androidx.annotation.Nullable;
abstract class AddContactState {
static class KeyAgreementListening extends AddContactState {
final Bitmap qrCode;
KeyAgreementListening(Bitmap qrCode) {
this.qrCode = qrCode;
}
}
static class QrCodeScanned extends AddContactState {
}
static class KeyAgreementWaiting extends AddContactState {
}
static class KeyAgreementStarted extends AddContactState {
}
static class ContactExchangeStarted extends AddContactState {
}
static class ContactExchangeFinished extends AddContactState {
final ContactExchangeResult result;
ContactExchangeFinished(ContactExchangeResult result) {
this.result = result;
}
}
static class Failed extends AddContactState {
/**
* Non-null if failed due to the scanned QR code version.
* True if the app producing the code is too old.
* False if the scanning app is too old.
*/
@Nullable
final Boolean qrCodeTooOld;
Failed(@Nullable Boolean qrCodeTooOld) {
this.qrCodeTooOld = qrCodeTooOld;
}
Failed() {
this(null);
}
}
abstract static class ContactExchangeResult {
static class Success extends ContactExchangeResult {
final Author remoteAuthor;
Success(Author remoteAuthor) {
this.remoteAuthor = remoteAuthor;
}
}
static class Error extends ContactExchangeResult {
@Nullable
final Author duplicateAuthor;
Error(@Nullable Author duplicateAuthor) {
this.duplicateAuthor = duplicateAuthor;
}
}
} // end ContactExchangeResult
}

View File

@@ -6,13 +6,19 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.Toast;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.NullSafety;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.ContactExchangeFinished;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.ContactExchangeResult;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.Failed;
import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
@@ -21,32 +27,32 @@ import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import androidx.annotation.UiThread;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProvider;
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.Objects.requireNonNull;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_BLUETOOTH_DISCOVERABLE;
import static org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision.ACCEPTED;
import static org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision.REFUSED;
import static org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision.UNKNOWN;
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.ACCEPTED;
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.REFUSED;
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.UNKNOWN;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public abstract class KeyAgreementActivity extends BriarActivity
public class AddNearbyContactActivity extends BriarActivity
implements BaseFragmentListener {
private static final Logger LOG =
getLogger(KeyAgreementActivity.class.getName());
getLogger(AddNearbyContactActivity.class.getName());
@Inject
ViewModelProvider.Factory viewModelFactory;
protected ContactExchangeViewModel viewModel;
private AddNearbyContactViewModel viewModel;
private AddNearbyContactPermissionManager permissionManager;
/**
@@ -62,7 +68,7 @@ public abstract class KeyAgreementActivity extends BriarActivity
public void injectActivity(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(this, viewModelFactory)
.get(ContactExchangeViewModel.class);
.get(AddNearbyContactViewModel.class);
permissionManager = new AddNearbyContactPermissionManager(this,
viewModel.isBluetoothSupported());
}
@@ -73,9 +79,10 @@ public abstract class KeyAgreementActivity extends BriarActivity
setContentView(R.layout.activity_fragment_container_toolbar);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
NullSafety.requireNonNull(getSupportActionBar())
.setDisplayHomeAsUpEnabled(true);
if (state == null) {
showInitialFragment(IntroFragment.newInstance());
showInitialFragment(AddNearbyContactIntroFragment.newInstance());
}
IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED);
bluetoothReceiver = new BluetoothStateReceiver();
@@ -90,6 +97,10 @@ public abstract class KeyAgreementActivity extends BriarActivity
viewModel.getShowQrCodeFragment().observeEvent(this, show -> {
if (show) showQrCodeFragment();
});
requireNonNull(getSupportActionBar())
.setTitle(R.string.add_contact_title);
viewModel.getState()
.observe(this, this::onAddContactStateChanged);
}
@Override
@@ -120,15 +131,6 @@ public abstract class KeyAgreementActivity extends BriarActivity
if (bluetoothReceiver != null) unregisterReceiver(bluetoothReceiver);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onActivityResult(int request, int result,
@Nullable Intent data) {
@@ -145,7 +147,15 @@ public abstract class KeyAgreementActivity extends BriarActivity
}
@Override
@UiThread
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions,
@@ -154,6 +164,16 @@ public abstract class KeyAgreementActivity extends BriarActivity
grantResults, this::showQrCodeFragmentIfAllowed);
}
@Override
public void onBackPressed() {
if (viewModel.getState().getValue() instanceof Failed) {
// finish this activity when going back in failed state
supportFinishAfterTransition();
} else {
super.onBackPressed();
}
}
private void requestBluetoothDiscoverable() {
if (!viewModel.isBluetoothSupported()) {
viewModel.bluetoothDecision = BluetoothDecision.NO_ADAPTER;
@@ -174,7 +194,8 @@ public abstract class KeyAgreementActivity extends BriarActivity
@SuppressWarnings("StatementWithEmptyBody")
private void showQrCodeFragmentIfAllowed() {
boolean continueClicked = // never set to null
requireNonNull(viewModel.getWasContinueClicked().getValue());
NullSafety.requireNonNull(
viewModel.getWasContinueClicked().getValue());
boolean permissionsGranted =
permissionManager.areEssentialPermissionsGranted();
if (isResumed && continueClicked && permissionsGranted) {
@@ -197,8 +218,8 @@ public abstract class KeyAgreementActivity extends BriarActivity
private void showQrCodeFragment() {
// FIXME #824
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentByTag(KeyAgreementFragment.TAG) == null) {
BaseFragment f = KeyAgreementFragment.newInstance();
if (fm.findFragmentByTag(AddNearbyContactFragment.TAG) == null) {
BaseFragment f = AddNearbyContactFragment.newInstance();
fm.beginTransaction()
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
.addToBackStack(f.getUniqueTag())
@@ -206,6 +227,65 @@ public abstract class KeyAgreementActivity extends BriarActivity
}
}
private void onAddContactStateChanged(AddContactState state) {
if (state instanceof ContactExchangeFinished) {
ContactExchangeResult result =
((ContactExchangeFinished) state).result;
onContactExchangeResult(result);
} else if (state instanceof Failed) {
// Remove navigation icon, so user can't go back when failed
// ErrorFragment will finish or relaunch this activity
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setNavigationIcon(null);
Boolean qrCodeTooOld = ((Failed) state).qrCodeTooOld;
onAddingContactFailed(qrCodeTooOld);
}
}
private void onContactExchangeResult(ContactExchangeResult result) {
if (result instanceof ContactExchangeResult.Success) {
Author remoteAuthor =
((ContactExchangeResult.Success) result).remoteAuthor;
String contactName = remoteAuthor.getName();
String text = getString(R.string.contact_added_toast, contactName);
Toast.makeText(this, text, LENGTH_LONG).show();
supportFinishAfterTransition();
} else if (result instanceof ContactExchangeResult.Error) {
Author duplicateAuthor =
((ContactExchangeResult.Error) result).duplicateAuthor;
if (duplicateAuthor == null) {
showErrorFragment();
} else {
String contactName = duplicateAuthor.getName();
String text =
getString(R.string.contact_already_exists, contactName);
Toast.makeText(this, text, LENGTH_LONG).show();
supportFinishAfterTransition();
}
} else throw new AssertionError();
}
private void onAddingContactFailed(@Nullable Boolean qrCodeTooOld) {
if (qrCodeTooOld == null) {
showErrorFragment();
} else {
String msg;
if (qrCodeTooOld) {
msg = getString(R.string.qr_code_too_old,
getString(R.string.app_name));
} else {
msg = getString(R.string.qr_code_too_new,
getString(R.string.app_name));
}
showNextFragment(AddNearbyContactErrorFragment.newInstance(msg));
}
}
private void showErrorFragment() {
showNextFragment(new AddNearbyContactErrorFragment());
}
private class BluetoothStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

View File

@@ -24,14 +24,14 @@ import static org.briarproject.briar.android.util.UiUtils.onSingleLinkClick;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ContactExchangeErrorFragment extends BaseFragment {
public class AddNearbyContactErrorFragment extends BaseFragment {
public static final String TAG =
ContactExchangeErrorFragment.class.getName();
AddNearbyContactErrorFragment.class.getName();
private static final String ERROR_MSG = "errorMessage";
public static ContactExchangeErrorFragment newInstance(String errorMsg) {
ContactExchangeErrorFragment f = new ContactExchangeErrorFragment();
public static AddNearbyContactErrorFragment newInstance(String errorMsg) {
AddNearbyContactErrorFragment f = new AddNearbyContactErrorFragment();
Bundle args = new Bundle();
args.putString(ERROR_MSG, errorMsg);
f.setArguments(args);
@@ -72,7 +72,7 @@ public class ContactExchangeErrorFragment extends BaseFragment {
tryAgain.setOnClickListener(view -> {
// Recreate the activity so we return to the intro fragment
FragmentActivity activity = requireActivity();
Intent i = new Intent(activity, ContactExchangeActivity.class);
Intent i = new Intent(activity, AddNearbyContactActivity.class);
i.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(i);
});

View File

@@ -14,11 +14,11 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.ContactExchangeStarted;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.Failed;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.KeyAgreementStarted;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.KeyAgreementWaiting;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.QrCodeScanned;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.ContactExchangeStarted;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.Failed;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementStarted;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementWaiting;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.QrCodeScanned;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.view.QrCodeView;
@@ -42,26 +42,26 @@ import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class KeyAgreementFragment extends BaseFragment
public class AddNearbyContactFragment extends BaseFragment
implements QrCodeView.FullscreenListener {
static final String TAG = KeyAgreementFragment.class.getName();
static final String TAG = AddNearbyContactFragment.class.getName();
private static final Logger LOG = Logger.getLogger(TAG);
@Inject
ViewModelProvider.Factory viewModelFactory;
private ContactExchangeViewModel viewModel;
private AddNearbyContactViewModel viewModel;
private CameraView cameraView;
private LinearLayout cameraOverlay;
private View statusView;
private QrCodeView qrCodeView;
private TextView status;
public static KeyAgreementFragment newInstance() {
public static AddNearbyContactFragment newInstance() {
Bundle args = new Bundle();
KeyAgreementFragment fragment = new KeyAgreementFragment();
AddNearbyContactFragment fragment = new AddNearbyContactFragment();
fragment.setArguments(args);
return fragment;
}
@@ -70,7 +70,7 @@ public class KeyAgreementFragment extends BaseFragment
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(ContactExchangeViewModel.class);
.get(AddNearbyContactViewModel.class);
}
@Nullable
@@ -93,7 +93,7 @@ public class KeyAgreementFragment extends BaseFragment
qrCodeView.setFullscreenListener(this);
viewModel.getState().observe(getViewLifecycleOwner(),
this::onContactAddingStateChanged);
this::onAddContactStateChanged);
}
@Override
@@ -153,10 +153,10 @@ public class KeyAgreementFragment extends BaseFragment
}
@UiThread
private void onContactAddingStateChanged(ContactAddingState state) {
if (state instanceof ContactAddingState.KeyAgreementListening) {
private void onAddContactStateChanged(AddContactState state) {
if (state instanceof AddContactState.KeyAgreementListening) {
Bitmap qrCode =
((ContactAddingState.KeyAgreementListening) state).qrCode;
((AddContactState.KeyAgreementListening) state).qrCode;
qrCodeView.setQrCode(qrCode);
} else if (state instanceof QrCodeScanned) {
try {

View File

@@ -21,20 +21,21 @@ import static android.view.View.FOCUS_DOWN;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class IntroFragment extends BaseFragment {
public class AddNearbyContactIntroFragment extends BaseFragment {
public static final String TAG = IntroFragment.class.getName();
public static final String TAG = AddNearbyContactIntroFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private ContactExchangeViewModel viewModel;
private AddNearbyContactViewModel viewModel;
private ScrollView scrollView;
public static IntroFragment newInstance() {
public static AddNearbyContactIntroFragment newInstance() {
Bundle args = new Bundle();
IntroFragment fragment = new IntroFragment();
AddNearbyContactIntroFragment
fragment = new AddNearbyContactIntroFragment();
fragment.setArguments(args);
return fragment;
}
@@ -43,7 +44,7 @@ public class IntroFragment extends BaseFragment {
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(ContactExchangeViewModel.class);
.get(AddNearbyContactViewModel.class);
}
@Nullable

View File

@@ -8,12 +8,12 @@ import dagger.Module;
import dagger.multibindings.IntoMap;
@Module
public abstract class ContactExchangeModule {
public abstract class AddNearbyContactModule {
@Binds
@IntoMap
@ViewModelKey(ContactExchangeViewModel.class)
@ViewModelKey(AddNearbyContactViewModel.class)
abstract ViewModel bindContactExchangeViewModel(
ContactExchangeViewModel contactExchangeViewModel);
AddNearbyContactViewModel addNearbyContactViewModel);
}

View File

@@ -40,13 +40,13 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
import org.briarproject.briar.R;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.ContactExchangeFinished;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.ContactExchangeStarted;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.KeyAgreementListening;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.KeyAgreementStarted;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.KeyAgreementWaiting;
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeResult.Error;
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeResult.Success;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.ContactExchangeFinished;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.ContactExchangeResult.Error;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.ContactExchangeResult.Success;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.ContactExchangeStarted;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementListening;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementStarted;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementWaiting;
import org.briarproject.briar.android.viewmodel.LiveEvent;
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
@@ -75,15 +75,15 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision.REFUSED;
import static org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision.UNKNOWN;
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.REFUSED;
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.UNKNOWN;
@NotNullByDefault
class ContactExchangeViewModel extends AndroidViewModel
class AddNearbyContactViewModel extends AndroidViewModel
implements EventListener, QrCodeDecoder.ResultCallback {
private static final Logger LOG =
getLogger(ContactExchangeViewModel.class.getName());
getLogger(AddNearbyContactViewModel.class.getName());
enum BluetoothDecision {
/**
@@ -135,7 +135,7 @@ class ContactExchangeViewModel extends AndroidViewModel
new MutableLiveEvent<>();
private final MutableLiveEvent<TransportId> transportStateChanged =
new MutableLiveEvent<>();
private final MutableLiveData<ContactAddingState> state =
private final MutableLiveData<AddContactState> state =
new MutableLiveData<>();
final QrCodeDecoder qrCodeDecoder;
@@ -164,7 +164,7 @@ class ContactExchangeViewModel extends AndroidViewModel
private volatile boolean gotLocalPayload = false, gotRemotePayload = false;
@Inject
ContactExchangeViewModel(Application app,
AddNearbyContactViewModel(Application app,
EventBus eventBus,
@IoExecutor Executor ioExecutor,
PluginManager pluginManager,
@@ -336,11 +336,11 @@ class ContactExchangeViewModel extends AndroidViewModel
} else if (e instanceof KeyAgreementAbortedEvent) {
LOG.info("KeyAgreementAbortedEvent received");
resetPayloadFlags();
state.setValue(new ContactAddingState.Failed());
state.setValue(new AddContactState.Failed());
} else if (e instanceof KeyAgreementFailedEvent) {
LOG.info("KeyAgreementFailedEvent received");
resetPayloadFlags();
state.setValue(new ContactAddingState.Failed());
state.setValue(new AddContactState.Failed());
}
}
@@ -377,16 +377,16 @@ class ContactExchangeViewModel extends AndroidViewModel
Payload remotePayload = payloadParser.parse(payloadBytes);
gotRemotePayload = true;
requireNonNull(task).connectAndRunProtocol(remotePayload);
state.postValue(new ContactAddingState.QrCodeScanned());
state.postValue(new AddContactState.QrCodeScanned());
} catch (UnsupportedVersionException e) {
resetPayloadFlags();
state.postValue(new ContactAddingState.Failed(e.isTooOld()));
state.postValue(new AddContactState.Failed(e.isTooOld()));
} catch (IOException | IllegalArgumentException e) {
LOG.log(WARNING, "QR Code Invalid", e);
Toast.makeText(getApplication(), R.string.qr_code_invalid,
LENGTH_LONG).show();
resetPayloadFlags();
state.postValue(new ContactAddingState.Failed());
state.postValue(new AddContactState.Failed());
}
}
@@ -448,7 +448,7 @@ class ContactExchangeViewModel extends AndroidViewModel
return showQrCodeFragment;
}
LiveData<ContactAddingState> getState() {
LiveData<AddContactState> getState() {
return state;
}

View File

@@ -1,55 +0,0 @@
package org.briarproject.briar.android.contact.add.nearby;
import android.graphics.Bitmap;
import androidx.annotation.Nullable;
abstract class ContactAddingState {
static class KeyAgreementListening extends ContactAddingState {
final Bitmap qrCode;
KeyAgreementListening(Bitmap qrCode) {
this.qrCode = qrCode;
}
}
static class QrCodeScanned extends ContactAddingState {
}
static class KeyAgreementWaiting extends ContactAddingState {
}
static class KeyAgreementStarted extends ContactAddingState {
}
static class ContactExchangeStarted extends ContactAddingState {
}
static class ContactExchangeFinished extends ContactAddingState {
final ContactExchangeResult result;
ContactExchangeFinished(ContactExchangeResult result) {
this.result = result;
}
}
static class Failed extends ContactAddingState {
/**
* Non-null if failed due to the scanned QR code version.
* True if the app producing the code is too old.
* False if the scanning app is too old.
*/
@Nullable
final Boolean qrCodeTooOld;
Failed(@Nullable Boolean qrCodeTooOld) {
this.qrCodeTooOld = qrCodeTooOld;
}
Failed() {
this(null);
}
}
}

View File

@@ -1,101 +0,0 @@
package org.briarproject.briar.android.contact.add.nearby;
import android.os.Bundle;
import android.widget.Toast;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.ContactExchangeFinished;
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.Failed;
import javax.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.Objects.requireNonNull;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ContactExchangeActivity extends KeyAgreementActivity {
@Override
public void onCreate(@Nullable Bundle state) {
super.onCreate(state);
requireNonNull(getSupportActionBar())
.setTitle(R.string.add_contact_title);
viewModel.getState()
.observe(this, this::onContactAddingStateChanged);
}
@Override
public void onBackPressed() {
if (viewModel.getState().getValue() instanceof Failed) {
// finish this activity when going back in failed state
supportFinishAfterTransition();
} else {
super.onBackPressed();
}
}
private void onContactAddingStateChanged(ContactAddingState state) {
if (state instanceof ContactExchangeFinished) {
ContactExchangeResult result =
((ContactExchangeFinished) state).result;
onContactExchangeResult(result);
} else if (state instanceof Failed) {
// Remove navigation icon, so user can't go back when failed
// ErrorFragment will finish or relaunch this activity
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setNavigationIcon(null);
Boolean qrCodeTooOld = ((Failed) state).qrCodeTooOld;
onAddingContactFailed(qrCodeTooOld);
}
}
private void onContactExchangeResult(ContactExchangeResult result) {
if (result instanceof ContactExchangeResult.Success) {
Author remoteAuthor =
((ContactExchangeResult.Success) result).remoteAuthor;
String contactName = remoteAuthor.getName();
String text = getString(R.string.contact_added_toast, contactName);
Toast.makeText(this, text, LENGTH_LONG).show();
supportFinishAfterTransition();
} else if (result instanceof ContactExchangeResult.Error) {
Author duplicateAuthor =
((ContactExchangeResult.Error) result).duplicateAuthor;
if (duplicateAuthor == null) {
showErrorFragment();
} else {
String contactName = duplicateAuthor.getName();
String text =
getString(R.string.contact_already_exists, contactName);
Toast.makeText(this, text, LENGTH_LONG).show();
supportFinishAfterTransition();
}
} else throw new AssertionError();
}
private void onAddingContactFailed(@Nullable Boolean qrCodeTooOld) {
if (qrCodeTooOld == null) {
showErrorFragment();
} else {
String msg;
if (qrCodeTooOld) {
msg = getString(R.string.qr_code_too_old,
getString(R.string.app_name));
} else {
msg = getString(R.string.qr_code_too_new,
getString(R.string.app_name));
}
showNextFragment(ContactExchangeErrorFragment.newInstance(msg));
}
}
private void showErrorFragment() {
showNextFragment(new ContactExchangeErrorFragment());
}
}

View File

@@ -1,30 +0,0 @@
package org.briarproject.briar.android.contact.add.nearby;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
abstract class ContactExchangeResult {
static class Success extends ContactExchangeResult {
final Author remoteAuthor;
Success(Author remoteAuthor) {
this.remoteAuthor = remoteAuthor;
}
}
static class Error extends ContactExchangeResult {
@Nullable
final Author duplicateAuthor;
Error(@Nullable Author duplicateAuthor) {
this.duplicateAuthor = duplicateAuthor;
}
}
}