mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 13:49:53 +01:00
Use new MailboxManager in Android UI
This commit is contained in:
@@ -5,6 +5,8 @@ import android.view.MenuItem;
|
|||||||
import android.widget.ProgressBar;
|
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.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;
|
||||||
@@ -20,6 +22,7 @@ import androidx.lifecycle.ViewModelProvider;
|
|||||||
|
|
||||||
import static android.view.View.INVISIBLE;
|
import static android.view.View.INVISIBLE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
|
import static android.widget.Toast.LENGTH_LONG;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.showFragment;
|
import static org.briarproject.briar.android.util.UiUtils.showFragment;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@@ -55,14 +58,14 @@ public class MailboxActivity extends BriarActivity {
|
|||||||
onNotSetup();
|
onNotSetup();
|
||||||
} else if (state instanceof MailboxState.ScanningQrCode) {
|
} else if (state instanceof MailboxState.ScanningQrCode) {
|
||||||
onScanningQrCode();
|
onScanningQrCode();
|
||||||
} else if (state instanceof MailboxState.SettingUp) {
|
} else if (state instanceof MailboxState.Pairing) {
|
||||||
onCodeScanned();
|
MailboxPairingState s =
|
||||||
} else if (state instanceof MailboxState.QrCodeWrong) {
|
((MailboxState.Pairing) state).pairingState;
|
||||||
onQrCodeWrong();
|
onMailboxPairingStateChanged(s);
|
||||||
} else if (state instanceof MailboxState.OfflineInSetup) {
|
} else if (state instanceof MailboxState.OfflineWhenPairing) {
|
||||||
onOffline();
|
onOffline();
|
||||||
} else if (state instanceof MailboxState.IsSetup) {
|
} else if (state instanceof MailboxState.IsPaired) {
|
||||||
onIsSetup(((MailboxState.IsSetup) state).mailboxStatus);
|
onIsPaired(((MailboxState.IsPaired) state).mailboxStatus);
|
||||||
} else {
|
} else {
|
||||||
throw new AssertionError("Unknown state: " + state);
|
throw new AssertionError("Unknown state: " + state);
|
||||||
}
|
}
|
||||||
@@ -80,9 +83,10 @@ public class MailboxActivity extends BriarActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
if (viewModel.getState()
|
MailboxState s = viewModel.getState().getLastValue();
|
||||||
.getLastValue() instanceof MailboxState.SettingUp) {
|
if (s instanceof MailboxState.Pairing &&
|
||||||
// don't go back in flow if we are already setting up mailbox
|
((MailboxState.Pairing) s).pairingState instanceof Pairing) {
|
||||||
|
// don't go back in flow if we are already pairing with the mailbox
|
||||||
supportFinishAfterTransition();
|
supportFinishAfterTransition();
|
||||||
} else {
|
} else {
|
||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
@@ -102,17 +106,43 @@ public class MailboxActivity extends BriarActivity {
|
|||||||
MailboxScanFragment.TAG);
|
MailboxScanFragment.TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onCodeScanned() {
|
private void onMailboxPairingStateChanged(MailboxPairingState s) {
|
||||||
showFragment(getSupportFragmentManager(),
|
progressBar.setVisibility(INVISIBLE);
|
||||||
new MailboxConnectingFragment(),
|
Fragment f;
|
||||||
MailboxConnectingFragment.TAG, false);
|
String tag;
|
||||||
}
|
boolean addToBackStack = true;
|
||||||
|
if (s instanceof MailboxPairingState.QrCodeReceived) {
|
||||||
private void onQrCodeWrong() {
|
// ignore, showing yet another progress fragment messes with back stack
|
||||||
Fragment f = ErrorFragment.newInstance(
|
return;
|
||||||
R.string.mailbox_setup_qr_code_wrong_title,
|
} else if (s instanceof MailboxPairingState.Pairing) {
|
||||||
R.string.mailbox_setup_qr_code_wrong_description);
|
f = new MailboxConnectingFragment();
|
||||||
showFragment(getSupportFragmentManager(), f, ErrorFragment.TAG);
|
tag = MailboxConnectingFragment.TAG;
|
||||||
|
addToBackStack = false;
|
||||||
|
} else if (s instanceof MailboxPairingState.InvalidQrCode) {
|
||||||
|
f = ErrorFragment.newInstance(
|
||||||
|
R.string.mailbox_setup_qr_code_wrong_title,
|
||||||
|
R.string.mailbox_setup_qr_code_wrong_description);
|
||||||
|
tag = ErrorFragment.TAG;
|
||||||
|
} else if (s instanceof MailboxPairingState.MailboxAlreadyPaired) {
|
||||||
|
// TODO
|
||||||
|
Toast.makeText(this, "MailboxAlreadyPaired", LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
} else if (s instanceof MailboxPairingState.ConnectionError) {
|
||||||
|
// TODO
|
||||||
|
Toast.makeText(this, "Connection Error", LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
} else if (s instanceof MailboxPairingState.AssertionError) {
|
||||||
|
// TODO
|
||||||
|
Toast.makeText(this, "Connection Error", LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
} else if (s instanceof MailboxPairingState.Paired) {
|
||||||
|
// TODO
|
||||||
|
Toast.makeText(this, "Connection Error", LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unhandled state: " + s.getClass());
|
||||||
|
}
|
||||||
|
showFragment(getSupportFragmentManager(), f, tag, addToBackStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onOffline() {
|
private void onOffline() {
|
||||||
@@ -120,9 +150,10 @@ public class MailboxActivity extends BriarActivity {
|
|||||||
OfflineFragment.TAG);
|
OfflineFragment.TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onIsSetup(MailboxStatus mailboxStatus) {
|
private void onIsPaired(MailboxStatus mailboxStatus) {
|
||||||
|
progressBar.setVisibility(INVISIBLE);
|
||||||
// TODO
|
// TODO
|
||||||
Toast.makeText(this, "NOT IMPLEMENTED", Toast.LENGTH_LONG).show();
|
Toast.makeText(this, "NOT IMPLEMENTED", LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package org.briarproject.briar.android.mailbox;
|
package org.briarproject.briar.android.mailbox;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxProperties;
|
import org.briarproject.bramble.api.mailbox.MailboxPairingState;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxStatus;
|
import org.briarproject.bramble.api.mailbox.MailboxStatus;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -13,29 +13,31 @@ class MailboxState {
|
|||||||
static class ScanningQrCode extends MailboxState {
|
static class ScanningQrCode extends MailboxState {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class SettingUp extends MailboxState {
|
static class Pairing extends MailboxState {
|
||||||
|
final MailboxPairingState pairingState;
|
||||||
|
|
||||||
|
Pairing(MailboxPairingState pairingState) {
|
||||||
|
this.pairingState = pairingState;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class QrCodeWrong extends MailboxState {
|
static class OfflineWhenPairing extends MailboxState {
|
||||||
}
|
|
||||||
|
|
||||||
static class OfflineInSetup extends MailboxState {
|
|
||||||
@Nullable
|
@Nullable
|
||||||
final MailboxProperties mailboxProperties;
|
final String qrCodePayload;
|
||||||
|
|
||||||
OfflineInSetup(@Nullable MailboxProperties mailboxProperties) {
|
OfflineWhenPairing(@Nullable String qrCodePayload) {
|
||||||
this.mailboxProperties = mailboxProperties;
|
this.qrCodePayload = qrCodePayload;
|
||||||
}
|
}
|
||||||
|
|
||||||
OfflineInSetup() {
|
OfflineWhenPairing() {
|
||||||
this(null);
|
this(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class IsSetup extends MailboxState {
|
static class IsPaired extends MailboxState {
|
||||||
final MailboxStatus mailboxStatus;
|
final MailboxStatus mailboxStatus;
|
||||||
|
|
||||||
IsSetup(MailboxStatus mailboxStatus) {
|
IsPaired(MailboxStatus mailboxStatus) {
|
||||||
this.mailboxStatus = mailboxStatus;
|
this.mailboxStatus = mailboxStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,14 @@ import android.app.Application;
|
|||||||
|
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.Consumer;
|
||||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
import org.briarproject.bramble.api.db.TransactionManager;
|
import org.briarproject.bramble.api.db.TransactionManager;
|
||||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
|
import org.briarproject.bramble.api.mailbox.MailboxManager;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxProperties;
|
import org.briarproject.bramble.api.mailbox.MailboxPairingState;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
|
import org.briarproject.bramble.api.mailbox.MailboxPairingTask;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxStatus;
|
import org.briarproject.bramble.api.mailbox.MailboxStatus;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.Plugin;
|
import org.briarproject.bramble.api.plugin.Plugin;
|
||||||
@@ -25,38 +24,34 @@ import org.briarproject.briar.android.viewmodel.DbViewModel;
|
|||||||
import org.briarproject.briar.android.viewmodel.LiveEvent;
|
import org.briarproject.briar.android.viewmodel.LiveEvent;
|
||||||
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import androidx.annotation.AnyThread;
|
||||||
|
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.WARNING;
|
|
||||||
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;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class MailboxViewModel extends DbViewModel
|
class MailboxViewModel extends DbViewModel
|
||||||
implements QrCodeDecoder.ResultCallback {
|
implements QrCodeDecoder.ResultCallback, Consumer<MailboxPairingState> {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
getLogger(MailboxViewModel.class.getName());
|
getLogger(MailboxViewModel.class.getName());
|
||||||
|
|
||||||
@SuppressWarnings("CharsetObjectCanBeUsed") // Requires minSdkVersion >= 19
|
|
||||||
private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
|
|
||||||
private static final int VERSION_REQUIRED = 32;
|
|
||||||
|
|
||||||
private final CryptoComponent crypto;
|
|
||||||
private final QrCodeDecoder qrCodeDecoder;
|
private final QrCodeDecoder qrCodeDecoder;
|
||||||
private final PluginManager pluginManager;
|
private final PluginManager pluginManager;
|
||||||
private final MailboxSettingsManager mailboxSettingsManager;
|
private final MailboxManager mailboxManager;
|
||||||
|
|
||||||
private final MutableLiveEvent<MailboxState> state =
|
private final MutableLiveEvent<MailboxState> state =
|
||||||
new MutableLiveEvent<>();
|
new MutableLiveEvent<>();
|
||||||
|
@Nullable
|
||||||
|
private MailboxPairingTask pairingTask = null;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
MailboxViewModel(
|
MailboxViewModel(
|
||||||
@@ -66,29 +61,43 @@ class MailboxViewModel extends DbViewModel
|
|||||||
TransactionManager db,
|
TransactionManager db,
|
||||||
AndroidExecutor androidExecutor,
|
AndroidExecutor androidExecutor,
|
||||||
@IoExecutor Executor ioExecutor,
|
@IoExecutor Executor ioExecutor,
|
||||||
CryptoComponent crypto,
|
|
||||||
PluginManager pluginManager,
|
PluginManager pluginManager,
|
||||||
MailboxSettingsManager mailboxSettingsManager) {
|
MailboxManager mailboxManager) {
|
||||||
super(app, dbExecutor, lifecycleManager, db, androidExecutor);
|
super(app, dbExecutor, lifecycleManager, db, androidExecutor);
|
||||||
this.crypto = crypto;
|
|
||||||
this.pluginManager = pluginManager;
|
this.pluginManager = pluginManager;
|
||||||
this.mailboxSettingsManager = mailboxSettingsManager;
|
this.mailboxManager = mailboxManager;
|
||||||
qrCodeDecoder = new QrCodeDecoder(androidExecutor, ioExecutor, this);
|
qrCodeDecoder = new QrCodeDecoder(androidExecutor, ioExecutor, this);
|
||||||
checkIfSetup();
|
checkIfSetup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCleared() {
|
||||||
|
super.onCleared();
|
||||||
|
MailboxPairingTask task = pairingTask;
|
||||||
|
if (task != null) {
|
||||||
|
task.removeObserver(this);
|
||||||
|
pairingTask = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void checkIfSetup() {
|
private void checkIfSetup() {
|
||||||
runOnDbThread(true, txn -> {
|
MailboxPairingTask task = mailboxManager.getCurrentPairingTask();
|
||||||
MailboxProperties props =
|
if (task == null) {
|
||||||
mailboxSettingsManager.getOwnMailboxProperties(txn);
|
runOnDbThread(true, txn -> {
|
||||||
if (props == null) state.postEvent(new NotSetup());
|
boolean isPaired = mailboxManager.isPaired(txn);
|
||||||
else {
|
if (isPaired) {
|
||||||
MailboxStatus mailboxStatus =
|
MailboxStatus mailboxStatus =
|
||||||
mailboxSettingsManager.getOwnMailboxStatus(txn);
|
mailboxManager.getMailboxStatus(txn);
|
||||||
state.postEvent(new MailboxState.IsSetup(mailboxStatus));
|
state.postEvent(new MailboxState.IsPaired(mailboxStatus));
|
||||||
}
|
} else {
|
||||||
}, this::handleException);
|
state.postEvent(new NotSetup());
|
||||||
|
}
|
||||||
|
}, this::handleException);
|
||||||
|
} else {
|
||||||
|
task.addObserver(this);
|
||||||
|
pairingTask = task;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@@ -96,7 +105,7 @@ class MailboxViewModel extends DbViewModel
|
|||||||
if (isTorActive()) {
|
if (isTorActive()) {
|
||||||
state.setEvent(new MailboxState.ScanningQrCode());
|
state.setEvent(new MailboxState.ScanningQrCode());
|
||||||
} else {
|
} else {
|
||||||
state.setEvent(new MailboxState.OfflineInSetup());
|
state.setEvent(new MailboxState.OfflineWhenPairing());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,53 +113,25 @@ class MailboxViewModel extends DbViewModel
|
|||||||
@IoExecutor
|
@IoExecutor
|
||||||
public void onQrCodeDecoded(Result result) {
|
public void onQrCodeDecoded(Result result) {
|
||||||
LOG.info("Got result from decoder");
|
LOG.info("Got result from decoder");
|
||||||
MailboxProperties properties;
|
onQrCodePayloadReceived(result.getText());
|
||||||
try {
|
|
||||||
properties = decodeQrCode(result.getText());
|
|
||||||
} catch (FormatException e) {
|
|
||||||
state.postEvent(new MailboxState.QrCodeWrong());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
onMailboxPropertiesReceived(properties);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@IoExecutor
|
@AnyThread
|
||||||
// TODO move this into core #2168
|
private void onQrCodePayloadReceived(String qrCodePayload) {
|
||||||
private MailboxProperties decodeQrCode(String payload)
|
|
||||||
throws FormatException {
|
|
||||||
byte[] bytes = payload.getBytes(ISO_8859_1);
|
|
||||||
if (bytes.length != 65) {
|
|
||||||
if (LOG.isLoggable(WARNING)) {
|
|
||||||
LOG.warning("QR code length is not 65: " + bytes.length);
|
|
||||||
}
|
|
||||||
throw new FormatException();
|
|
||||||
}
|
|
||||||
int version = bytes[0] & 0xFF;
|
|
||||||
if (version != VERSION_REQUIRED) {
|
|
||||||
if (LOG.isLoggable(WARNING)) {
|
|
||||||
LOG.warning("QR code has not version " + VERSION_REQUIRED +
|
|
||||||
": " + version);
|
|
||||||
}
|
|
||||||
throw new FormatException();
|
|
||||||
}
|
|
||||||
LOG.info("QR code is valid");
|
|
||||||
byte[] onionPubKey = Arrays.copyOfRange(bytes, 1, 33);
|
|
||||||
String onionAddress = crypto.encodeOnionAddress(onionPubKey);
|
|
||||||
byte[] tokenBytes = Arrays.copyOfRange(bytes, 33, 65);
|
|
||||||
MailboxAuthToken setupToken = new MailboxAuthToken(tokenBytes);
|
|
||||||
return new MailboxProperties(onionAddress, setupToken, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onMailboxPropertiesReceived(MailboxProperties properties) {
|
|
||||||
if (isTorActive()) {
|
if (isTorActive()) {
|
||||||
// TODO pass props to core #2168
|
pairingTask = mailboxManager.startPairingTask(qrCodePayload);
|
||||||
state.postEvent(new MailboxState.SettingUp());
|
pairingTask.addObserver(this);
|
||||||
} else {
|
} else {
|
||||||
state.postEvent(new MailboxState.OfflineInSetup(properties));
|
state.postEvent(new MailboxState.OfflineWhenPairing(qrCodePayload));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO ideally also move this into core #2168
|
@UiThread
|
||||||
|
@Override
|
||||||
|
public void accept(MailboxPairingState mailboxPairingState) {
|
||||||
|
state.setEvent(new MailboxState.Pairing(mailboxPairingState));
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isTorActive() {
|
private boolean isTorActive() {
|
||||||
Plugin plugin = pluginManager.getPlugin(TorConstants.ID);
|
Plugin plugin = pluginManager.getPlugin(TorConstants.ID);
|
||||||
return plugin != null && plugin.getState() == ACTIVE;
|
return plugin != null && plugin.getState() == ACTIVE;
|
||||||
@@ -158,13 +139,13 @@ class MailboxViewModel extends DbViewModel
|
|||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
void tryAgainWhenOffline() {
|
void tryAgainWhenOffline() {
|
||||||
MailboxState.OfflineInSetup offline =
|
MailboxState.OfflineWhenPairing offline =
|
||||||
(MailboxState.OfflineInSetup) requireNonNull(
|
(MailboxState.OfflineWhenPairing) requireNonNull(
|
||||||
state.getLastValue());
|
state.getLastValue());
|
||||||
if (offline.mailboxProperties == null) {
|
if (offline.qrCodePayload == null) {
|
||||||
onScanButtonClicked();
|
onScanButtonClicked();
|
||||||
} else {
|
} else {
|
||||||
onMailboxPropertiesReceived(offline.mailboxProperties);
|
onQrCodePayloadReceived(offline.qrCodePayload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user