mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 20:59:54 +01:00
Implement UI for mailbox pairing error and final states
This commit is contained in:
@@ -44,6 +44,7 @@ import org.briarproject.briar.android.hotspot.ManualHotspotFragment;
|
|||||||
import org.briarproject.briar.android.hotspot.QrHotspotFragment;
|
import org.briarproject.briar.android.hotspot.QrHotspotFragment;
|
||||||
import org.briarproject.briar.android.logging.CachingLogHandler;
|
import org.briarproject.briar.android.logging.CachingLogHandler;
|
||||||
import org.briarproject.briar.android.login.SignInReminderReceiver;
|
import org.briarproject.briar.android.login.SignInReminderReceiver;
|
||||||
|
import org.briarproject.briar.android.mailbox.ErrorFragment;
|
||||||
import org.briarproject.briar.android.mailbox.MailboxScanFragment;
|
import org.briarproject.briar.android.mailbox.MailboxScanFragment;
|
||||||
import org.briarproject.briar.android.mailbox.OfflineFragment;
|
import org.briarproject.briar.android.mailbox.OfflineFragment;
|
||||||
import org.briarproject.briar.android.mailbox.SetupDownloadFragment;
|
import org.briarproject.briar.android.mailbox.SetupDownloadFragment;
|
||||||
@@ -248,4 +249,6 @@ public interface AndroidComponent
|
|||||||
void inject(MailboxScanFragment mailboxScanFragment);
|
void inject(MailboxScanFragment mailboxScanFragment);
|
||||||
|
|
||||||
void inject(OfflineFragment offlineFragment);
|
void inject(OfflineFragment offlineFragment);
|
||||||
|
|
||||||
|
void inject(ErrorFragment errorFragment);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,13 @@ public class FinalFragment extends Fragment {
|
|||||||
|
|
||||||
private NestedScrollView scrollView;
|
private NestedScrollView scrollView;
|
||||||
protected Button buttonView;
|
protected Button buttonView;
|
||||||
|
protected final OnBackPressedCallback onBackPressedCallback =
|
||||||
|
new OnBackPressedCallback(true) {
|
||||||
|
@Override
|
||||||
|
public void handleOnBackPressed() {
|
||||||
|
onBackButtonPressed();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
@@ -95,13 +102,8 @@ public class FinalFragment extends Fragment {
|
|||||||
|
|
||||||
AppCompatActivity a = (AppCompatActivity) requireActivity();
|
AppCompatActivity a = (AppCompatActivity) requireActivity();
|
||||||
a.setTitle(args.getInt(ARG_TITLE));
|
a.setTitle(args.getInt(ARG_TITLE));
|
||||||
a.getOnBackPressedDispatcher().addCallback(
|
a.getOnBackPressedDispatcher()
|
||||||
getViewLifecycleOwner(), new OnBackPressedCallback(true) {
|
.addCallback(getViewLifecycleOwner(), onBackPressedCallback);
|
||||||
@Override
|
|
||||||
public void handleOnBackPressed() {
|
|
||||||
onBackButtonPressed();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.briar.android.mailbox;
|
package org.briarproject.briar.android.mailbox;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -10,8 +11,14 @@ import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
|||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.fragment.FinalFragment;
|
import org.briarproject.briar.android.fragment.FinalFragment;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
|
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -29,21 +36,35 @@ public class ErrorFragment extends FinalFragment {
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ViewModelProvider.Factory viewModelFactory;
|
||||||
|
|
||||||
|
private MailboxViewModel viewModel;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
FragmentActivity activity = requireActivity();
|
||||||
|
getAndroidComponent(activity).inject(this);
|
||||||
|
viewModel = new ViewModelProvider(activity, viewModelFactory)
|
||||||
|
.get(MailboxViewModel.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater,
|
public View onCreateView(LayoutInflater inflater,
|
||||||
@Nullable ViewGroup container,
|
@Nullable ViewGroup container,
|
||||||
@Nullable Bundle savedInstanceState) {
|
@Nullable Bundle savedInstanceState) {
|
||||||
View v = super.onCreateView(inflater, container, savedInstanceState);
|
View v = super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
onBackPressedCallback.remove();
|
||||||
buttonView.setText(R.string.try_again_button);
|
buttonView.setText(R.string.try_again_button);
|
||||||
|
buttonView.setOnClickListener(view -> {
|
||||||
|
getParentFragmentManager().popBackStackImmediate();
|
||||||
|
viewModel.tryAgainAfterError();
|
||||||
|
});
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onBackButtonPressed() {
|
|
||||||
requireActivity().getSupportFragmentManager().popBackStack();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldHideActionBarBackButton() {
|
protected boolean shouldHideActionBarBackButton() {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -6,18 +6,19 @@ import android.widget.ProgressBar;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxPairingState;
|
import org.briarproject.bramble.api.mailbox.MailboxPairingState;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxPairingState.Pairing;
|
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxStatus;
|
import org.briarproject.bramble.api.mailbox.MailboxStatus;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
|
import org.briarproject.briar.android.fragment.FinalFragment;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
import static android.view.View.INVISIBLE;
|
import static android.view.View.INVISIBLE;
|
||||||
@@ -84,9 +85,9 @@ public class MailboxActivity extends BriarActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
MailboxState s = viewModel.getState().getLastValue();
|
MailboxState s = viewModel.getState().getLastValue();
|
||||||
if (s instanceof MailboxState.Pairing &&
|
if (s instanceof MailboxState.Pairing) {
|
||||||
((MailboxState.Pairing) s).pairingState instanceof Pairing) {
|
// don't go back in the flow if we are already pairing
|
||||||
// don't go back in flow if we are already pairing with the mailbox
|
// with the mailbox. We provide a try-again button instead.
|
||||||
supportFinishAfterTransition();
|
supportFinishAfterTransition();
|
||||||
} else {
|
} else {
|
||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
@@ -102,47 +103,63 @@ public class MailboxActivity extends BriarActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onScanningQrCode() {
|
private void onScanningQrCode() {
|
||||||
showFragment(getSupportFragmentManager(), new MailboxScanFragment(),
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
MailboxScanFragment.TAG);
|
if (fm.findFragmentByTag(MailboxScanFragment.TAG) != null) {
|
||||||
|
// if the scanner is already on the back stack, pop back to it
|
||||||
|
// instead of adding it to the stack again
|
||||||
|
fm.popBackStackImmediate(MailboxScanFragment.TAG, 0);
|
||||||
|
} else {
|
||||||
|
showFragment(fm, new MailboxScanFragment(),
|
||||||
|
MailboxScanFragment.TAG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onMailboxPairingStateChanged(MailboxPairingState s) {
|
private void onMailboxPairingStateChanged(MailboxPairingState s) {
|
||||||
progressBar.setVisibility(INVISIBLE);
|
progressBar.setVisibility(INVISIBLE);
|
||||||
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
Fragment f;
|
Fragment f;
|
||||||
String tag;
|
String tag;
|
||||||
boolean addToBackStack = true;
|
|
||||||
if (s instanceof MailboxPairingState.QrCodeReceived) {
|
if (s instanceof MailboxPairingState.QrCodeReceived) {
|
||||||
// ignore, showing yet another progress fragment messes with back stack
|
// ignore, showing yet another progress fragment messes with back stack
|
||||||
return;
|
return;
|
||||||
} else if (s instanceof MailboxPairingState.Pairing) {
|
} else if (s instanceof MailboxPairingState.Pairing) {
|
||||||
|
if (fm.getBackStackEntryCount() == 0) {
|
||||||
|
// We re-launched into an existing state,
|
||||||
|
// need to re-populate the back stack.
|
||||||
|
repopulateBackStack();
|
||||||
|
}
|
||||||
f = new MailboxConnectingFragment();
|
f = new MailboxConnectingFragment();
|
||||||
tag = MailboxConnectingFragment.TAG;
|
tag = MailboxConnectingFragment.TAG;
|
||||||
addToBackStack = false;
|
|
||||||
} else if (s instanceof MailboxPairingState.InvalidQrCode) {
|
} else if (s instanceof MailboxPairingState.InvalidQrCode) {
|
||||||
f = ErrorFragment.newInstance(
|
f = ErrorFragment.newInstance(
|
||||||
R.string.mailbox_setup_qr_code_wrong_title,
|
R.string.mailbox_setup_qr_code_wrong_title,
|
||||||
R.string.mailbox_setup_qr_code_wrong_description);
|
R.string.mailbox_setup_qr_code_wrong_description);
|
||||||
tag = ErrorFragment.TAG;
|
tag = ErrorFragment.TAG;
|
||||||
} else if (s instanceof MailboxPairingState.MailboxAlreadyPaired) {
|
} else if (s instanceof MailboxPairingState.MailboxAlreadyPaired) {
|
||||||
// TODO
|
f = ErrorFragment.newInstance(
|
||||||
Toast.makeText(this, "MailboxAlreadyPaired", LENGTH_LONG).show();
|
R.string.mailbox_setup_already_paired_title,
|
||||||
return;
|
R.string.mailbox_setup_already_paired_description);
|
||||||
|
tag = ErrorFragment.TAG;
|
||||||
} else if (s instanceof MailboxPairingState.ConnectionError) {
|
} else if (s instanceof MailboxPairingState.ConnectionError) {
|
||||||
// TODO
|
f = ErrorFragment.newInstance(
|
||||||
Toast.makeText(this, "Connection Error", LENGTH_LONG).show();
|
R.string.mailbox_setup_io_error_title,
|
||||||
return;
|
R.string.mailbox_setup_io_error_description);
|
||||||
} else if (s instanceof MailboxPairingState.AssertionError) {
|
tag = ErrorFragment.TAG;
|
||||||
// TODO
|
} else if (s instanceof MailboxPairingState.UnexpectedError) {
|
||||||
Toast.makeText(this, "Connection Error", LENGTH_LONG).show();
|
f = ErrorFragment.newInstance(
|
||||||
return;
|
R.string.mailbox_setup_assertion_error_title,
|
||||||
|
R.string.mailbox_setup_assertion_error_description);
|
||||||
|
tag = ErrorFragment.TAG;
|
||||||
} else if (s instanceof MailboxPairingState.Paired) {
|
} else if (s instanceof MailboxPairingState.Paired) {
|
||||||
// TODO
|
f = FinalFragment.newInstance(R.string.mailbox_setup_paired_title,
|
||||||
Toast.makeText(this, "Connection Error", LENGTH_LONG).show();
|
R.drawable.ic_check_circle_outline,
|
||||||
return;
|
R.color.briar_brand_green,
|
||||||
|
R.string.mailbox_setup_paired_description);
|
||||||
|
tag = FinalFragment.TAG;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Unhandled state: " + s.getClass());
|
throw new IllegalStateException("Unhandled state: " + s.getClass());
|
||||||
}
|
}
|
||||||
showFragment(getSupportFragmentManager(), f, tag, addToBackStack);
|
showFragment(fm, f, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onOffline() {
|
private void onOffline() {
|
||||||
@@ -156,4 +173,12 @@ public class MailboxActivity extends BriarActivity {
|
|||||||
Toast.makeText(this, "NOT IMPLEMENTED", LENGTH_LONG).show();
|
Toast.makeText(this, "NOT IMPLEMENTED", LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void repopulateBackStack() {
|
||||||
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
|
onNotSetup();
|
||||||
|
showFragment(fm, new SetupDownloadFragment(),
|
||||||
|
SetupDownloadFragment.TAG);
|
||||||
|
onScanningQrCode();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ class MailboxState {
|
|||||||
Pairing(MailboxPairingState pairingState) {
|
Pairing(MailboxPairingState pairingState) {
|
||||||
this.pairingState = pairingState;
|
this.pairingState = pairingState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
String getQrCodePayload() {
|
||||||
|
return pairingState.qrCodePayload;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class OfflineWhenPairing extends MailboxState {
|
static class OfflineWhenPairing extends MailboxState {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
|
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
||||||
|
|
||||||
@@ -129,6 +130,10 @@ class MailboxViewModel extends DbViewModel
|
|||||||
@UiThread
|
@UiThread
|
||||||
@Override
|
@Override
|
||||||
public void accept(MailboxPairingState mailboxPairingState) {
|
public void accept(MailboxPairingState mailboxPairingState) {
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("New pairing state: " +
|
||||||
|
mailboxPairingState.getClass().getSimpleName());
|
||||||
|
}
|
||||||
state.setEvent(new MailboxState.Pairing(mailboxPairingState));
|
state.setEvent(new MailboxState.Pairing(mailboxPairingState));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +154,17 @@ class MailboxViewModel extends DbViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
void tryAgainAfterError() {
|
||||||
|
MailboxState.Pairing pairing = (MailboxState.Pairing)
|
||||||
|
requireNonNull(state.getLastValue());
|
||||||
|
if (pairing.getQrCodePayload() == null) {
|
||||||
|
onScanButtonClicked();
|
||||||
|
} else {
|
||||||
|
onQrCodePayloadReceived(pairing.getQrCodePayload());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
QrCodeDecoder getQrCodeDecoder() {
|
QrCodeDecoder getQrCodeDecoder() {
|
||||||
return qrCodeDecoder;
|
return qrCodeDecoder;
|
||||||
|
|||||||
@@ -625,6 +625,15 @@
|
|||||||
<string name="mailbox_setup_connecting">Connecting…</string>
|
<string name="mailbox_setup_connecting">Connecting…</string>
|
||||||
<string name="mailbox_setup_qr_code_wrong_title">Wrong QR code</string>
|
<string name="mailbox_setup_qr_code_wrong_title">Wrong QR code</string>
|
||||||
<string name="mailbox_setup_qr_code_wrong_description">The scanned code is invalid. Please open the Briar Mailbox app on your mailbox device and scan the QR code it presents.</string>
|
<string name="mailbox_setup_qr_code_wrong_description">The scanned code is invalid. Please open the Briar Mailbox app on your mailbox device and scan the QR code it presents.</string>
|
||||||
|
<string name="mailbox_setup_already_paired_title">Mailbox already linked</string>
|
||||||
|
<string name="mailbox_setup_already_paired_description">Unlink the mailbox on your other device and try again.</string>
|
||||||
|
<string name="mailbox_setup_io_error_title">Could not connect</string>
|
||||||
|
<string name="mailbox_setup_io_error_description">Ensure that both devices are connected to the internet and try again.</string>
|
||||||
|
<string name="mailbox_setup_assertion_error_title">Mailbox Error</string>
|
||||||
|
<string name="mailbox_setup_assertion_error_description">Please send feedback (with anonymous data) via the Briar app if the issue persists.</string>
|
||||||
|
<string name="mailbox_setup_paired_title">Connected</string>
|
||||||
|
<string name="mailbox_setup_paired_description">The mailbox has been successfully linked.\n
|
||||||
|
\nFor ideal message delivery, keep the mailbox device connected to a charger and online.</string>
|
||||||
<string name="tor_offline_title">Offline</string>
|
<string name="tor_offline_title">Offline</string>
|
||||||
<string name="tor_offline_description">Ensure that this device is online and connections to the internet are allowed.\n\nAfterwards, wait for the globe icon in connection settings to turn green.</string>
|
<string name="tor_offline_description">Ensure that this device is online and connections to the internet are allowed.\n\nAfterwards, wait for the globe icon in connection settings to turn green.</string>
|
||||||
<string name="tor_offline_button_check">Check connection settings</string>
|
<string name="tor_offline_button_check">Check connection settings</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user