Make a ReturnShardFragment, based on ContactExchangeFragment

This commit is contained in:
ameba23
2021-04-08 16:43:39 +02:00
parent 73ce6c2fb0
commit 61453b96ab
5 changed files with 209 additions and 6 deletions

View File

@@ -91,6 +91,7 @@ import org.briarproject.briar.android.socialbackup.ShardsSentFragment;
import org.briarproject.briar.android.socialbackup.ThresholdSelectorFragment;
import org.briarproject.briar.android.socialbackup.creation.CreateBackupModule;
import org.briarproject.briar.android.socialbackup.recover.ReturnShardActivity;
import org.briarproject.briar.android.socialbackup.recover.ReturnShardFragment;
import org.briarproject.briar.android.splash.SplashScreenActivity;
import org.briarproject.briar.android.test.TestDataActivity;
@@ -276,4 +277,6 @@ public interface ActivityComponent {
void inject(ExistingBackupFragment existingBackupFragment);
void inject(NewOrRecoverFragment newOrRecoverFragment);
void inject(ReturnShardFragment returnShardFragment);
}

View File

@@ -2,7 +2,7 @@ package org.briarproject.briar.android.contact.add.nearby;
import java.io.IOException;
class CameraException extends IOException {
public class CameraException extends IOException {
CameraException(String message) {
super(message);

View File

@@ -14,12 +14,10 @@ import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
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.AddNearbyContactPermissionManager;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.util.RequestBluetoothDiscoverable;
import org.briarproject.briar.api.socialbackup.BackupPayload;
import org.briarproject.briar.api.socialbackup.MessageParser;
import org.briarproject.briar.api.socialbackup.ReturnShardPayload;
import org.briarproject.briar.api.socialbackup.Shard;
@@ -208,8 +206,8 @@ public class ReturnShardActivity extends BaseActivity
private void showQrCodeFragment() {
// FIXME #824
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentByTag(AddNearbyContactFragment.TAG) == null) {
BaseFragment f = AddNearbyContactFragment.newInstance();
if (fm.findFragmentByTag(ReturnShardFragment.TAG) == null) {
BaseFragment f = ReturnShardFragment.newInstance();
fm.beginTransaction()
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
.addToBackStack(f.getUniqueTag())

View File

@@ -0,0 +1,198 @@
package org.briarproject.briar.android.socialbackup.recover;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
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.CameraException;
import org.briarproject.briar.android.contact.add.nearby.CameraView;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.view.QrCodeView;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import androidx.annotation.UiThread;
import androidx.lifecycle.ViewModelProvider;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.widget.LinearLayout.HORIZONTAL;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ReturnShardFragment extends BaseFragment
implements QrCodeView.FullscreenListener {
public static final String TAG = org.briarproject.briar.android.contact.add.nearby.AddNearbyContactFragment.class.getName();
private static final Logger LOG = Logger.getLogger(TAG);
@Inject
ViewModelProvider.Factory viewModelFactory;
private ReturnShardViewModel viewModel;
private CameraView cameraView;
private LinearLayout cameraOverlay;
private View statusView;
private QrCodeView qrCodeView;
private TextView status;
public static ReturnShardFragment newInstance() {
Bundle args = new Bundle();
ReturnShardFragment fragment = new ReturnShardFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(ReturnShardViewModel.class);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_keyagreement_qr, container,
false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
cameraView = view.findViewById(R.id.camera_view);
cameraOverlay = view.findViewById(R.id.camera_overlay);
statusView = view.findViewById(R.id.status_container);
status = view.findViewById(R.id.connect_status);
qrCodeView = view.findViewById(R.id.qr_code_view);
qrCodeView.setFullscreenListener(this);
viewModel.getState().observe(getViewLifecycleOwner(),
this::onReturnShardStateChanged);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
requireActivity().setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR);
cameraView.setPreviewConsumer(viewModel.getQrCodeDecoder());
}
@Override
public void onStart() {
super.onStart();
try {
cameraView.start();
} catch (CameraException e) {
logCameraExceptionAndFinish(e);
}
}
@Override
public void onStop() {
super.onStop();
try {
cameraView.stop();
} catch (CameraException e) {
logCameraExceptionAndFinish(e);
}
}
@Override
public void onDestroy() {
requireActivity()
.setRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
super.onDestroy();
}
@Override
public void setFullscreen(boolean fullscreen) {
LinearLayout.LayoutParams statusParams, qrCodeParams;
if (fullscreen) {
// Grow the QR code view to fill its parent
statusParams = new LinearLayout.LayoutParams(0, 0, 0f);
qrCodeParams = new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT, 1f);
} else {
// Shrink the QR code view to fill half its parent
if (cameraOverlay.getOrientation() == HORIZONTAL) {
statusParams = new LinearLayout.LayoutParams(0, MATCH_PARENT, 1f);
qrCodeParams = new LinearLayout.LayoutParams(0, MATCH_PARENT, 1f);
} else {
statusParams = new LinearLayout.LayoutParams(MATCH_PARENT, 0, 1f);
qrCodeParams = new LinearLayout.LayoutParams(MATCH_PARENT, 0, 1f);
}
}
statusView.setLayoutParams(statusParams);
qrCodeView.setLayoutParams(qrCodeParams);
cameraOverlay.invalidate();
}
@UiThread
private void onReturnShardStateChanged(@Nullable ReturnShardState state) {
if (state instanceof ReturnShardState.KeyAgreementListening) {
Bitmap qrCode =
((ReturnShardState.KeyAgreementListening) state).qrCode;
qrCodeView.setQrCode(qrCode);
} else if (state instanceof ReturnShardState.QrCodeScanned) {
try {
cameraView.stop();
} catch (CameraException e) {
logCameraExceptionAndFinish(e);
}
cameraView.setVisibility(INVISIBLE);
statusView.setVisibility(VISIBLE);
status.setText(R.string.connecting_to_device);
} else if (state instanceof ReturnShardState.KeyAgreementWaiting) {
status.setText(R.string.waiting_for_contact_to_scan);
} else if (state instanceof ReturnShardState.KeyAgreementStarted) {
qrCodeView.setVisibility(INVISIBLE);
status.setText(R.string.authenticating_with_device);
} else if (state instanceof ReturnShardState.SocialBackupExchangeStarted) {
status.setText(R.string.exchanging_contact_details);
} else if (state instanceof ReturnShardState.Failed) {
// the activity will replace this fragment with an error fragment
statusView.setVisibility(INVISIBLE);
cameraView.setVisibility(INVISIBLE);
}
}
@Override
public String getUniqueTag() {
return TAG;
}
@UiThread
private void logCameraExceptionAndFinish(CameraException e) {
logException(LOG, WARNING, e);
Toast.makeText(getActivity(), R.string.camera_error,
LENGTH_LONG).show();
finish();
}
@Override
protected void finish() {
requireActivity().getSupportFragmentManager().popBackStack();
}
}

View File

@@ -410,7 +410,7 @@ class ReturnShardViewModel extends AndroidViewModel
@Override
@IoExecutor
public void onQrCodeDecoded(Result result) {
LOG.info("Got result from decoder");
LOG.info("Got result from decoder"+gotLocalPayload+gotRemotePayload);
// Ignore results until the KeyAgreementTask is ready
if (!gotLocalPayload || gotRemotePayload) return;
try {
@@ -538,4 +538,8 @@ class ReturnShardViewModel extends AndroidViewModel
public void setReturnShardPayload(ReturnShardPayload returnShardPayload) {
this.returnShardPayload = returnShardPayload;
}
QrCodeDecoder getQrCodeDecoder() {
return qrCodeDecoder;
}
}