diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxPairingState.java b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxPairingState.java
index 8e129e2fe..47c055aad 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxPairingState.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/MailboxPairingState.java
@@ -2,10 +2,27 @@ package org.briarproject.bramble.api.mailbox;
public abstract class MailboxPairingState {
- public static class QrCodeReceived extends MailboxPairingState {
+ public abstract static class Pending extends MailboxPairingState {
+
+ public final long timeStarted;
+
+ private Pending(long timeStarted) {
+ this.timeStarted = timeStarted;
+ }
}
- public static class Pairing extends MailboxPairingState {
+ public static class QrCodeReceived extends Pending {
+
+ public QrCodeReceived(long timeStarted) {
+ super(timeStarted);
+ }
+ }
+
+ public static class Pairing extends Pending {
+
+ public Pairing(long timeStarted) {
+ super(timeStarted);
+ }
}
public static class Paired extends MailboxPairingState {
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImpl.java
index 544a38bf1..8ce25be9d 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImpl.java
@@ -52,6 +52,7 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
private final MailboxApi api;
private final MailboxSettingsManager mailboxSettingsManager;
private final MailboxUpdateManager mailboxUpdateManager;
+ private final long timeStarted;
private final Object lock = new Object();
@GuardedBy("lock")
@@ -77,7 +78,8 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
this.api = api;
this.mailboxSettingsManager = mailboxSettingsManager;
this.mailboxUpdateManager = mailboxUpdateManager;
- state = new MailboxPairingState.QrCodeReceived();
+ timeStarted = clock.currentTimeMillis();
+ state = new MailboxPairingState.QrCodeReceived(timeStarted);
}
@Override
@@ -114,7 +116,7 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
private void pairMailbox() throws IOException, ApiException, DbException {
MailboxProperties mailboxProperties = decodeQrCodePayload(payload);
- setState(new MailboxPairingState.Pairing());
+ setState(new MailboxPairingState.Pairing(timeStarted));
MailboxProperties ownerProperties = api.setup(mailboxProperties);
long time = clock.currentTimeMillis();
db.transaction(false, txn -> {
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImplTest.java
index fbc817d3f..86763a525 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImplTest.java
@@ -68,8 +68,7 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
@Test
public void testInitialQrCodeReceivedState() {
- MailboxPairingTask task =
- factory.createPairingTask(getRandomString(42));
+ MailboxPairingTask task = createPairingTask(getRandomString(42));
task.addObserver(state ->
assertTrue(state instanceof MailboxPairingState.QrCodeReceived)
);
@@ -77,15 +76,14 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
@Test
public void testInvalidQrCode() {
- MailboxPairingTask task1 =
- factory.createPairingTask(getRandomString(42));
+ MailboxPairingTask task1 = createPairingTask(getRandomString(42));
task1.run();
task1.addObserver(state ->
assertTrue(state instanceof MailboxPairingState.InvalidQrCode)
);
String goodLength = "00" + getRandomString(63);
- MailboxPairingTask task2 = factory.createPairingTask(goodLength);
+ MailboxPairingTask task2 = createPairingTask(goodLength);
task2.run();
task2.addObserver(state ->
assertTrue(state instanceof MailboxPairingState.InvalidQrCode)
@@ -121,7 +119,7 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
}});
AtomicInteger i = new AtomicInteger(0);
- MailboxPairingTask task = factory.createPairingTask(validPayload);
+ MailboxPairingTask task = createPairingTask(validPayload);
task.addObserver(state -> {
if (i.get() == 0) {
assertEquals(MailboxPairingState.QrCodeReceived.class,
@@ -165,7 +163,7 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
will(throwException(e));
}});
- MailboxPairingTask task = factory.createPairingTask(validPayload);
+ MailboxPairingTask task = createPairingTask(validPayload);
task.run();
task.addObserver(state -> assertEquals(state.getClass(), s));
}
@@ -188,7 +186,7 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
will(throwException(new DbException()));
}});
- MailboxPairingTask task = factory.createPairingTask(validPayload);
+ MailboxPairingTask task = createPairingTask(validPayload);
task.run();
task.addObserver(state -> assertEquals(state.getClass(),
MailboxPairingState.UnexpectedError.class));
@@ -202,4 +200,12 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
p1.getServerSupports().equals(p2.getServerSupports()));
}
+ private MailboxPairingTask createPairingTask(String qrCodePayload) {
+ context.checking(new Expectations() {{
+ oneOf(clock).currentTimeMillis();
+ will(returnValue(time));
+ }});
+
+ return factory.createPairingTask(qrCodePayload);
+ }
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java
index c72993776..64aaeacd7 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java
@@ -158,11 +158,9 @@ public class MailboxActivity extends BriarActivity {
}
Fragment f;
String tag;
- if (s instanceof MailboxPairingState.QrCodeReceived) {
- f = new MailboxConnectingFragment();
- tag = MailboxConnectingFragment.TAG;
- } else if (s instanceof MailboxPairingState.Pairing) {
- f = new MailboxConnectingFragment();
+ if (s instanceof MailboxPairingState.Pending) {
+ long timeStarted = ((MailboxPairingState.Pending) s).timeStarted;
+ f = MailboxConnectingFragment.newInstance(timeStarted);
tag = MailboxConnectingFragment.TAG;
} else if (s instanceof MailboxPairingState.InvalidQrCode) {
f = ErrorFragment.newInstance(
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxConnectingFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxConnectingFragment.java
index 3da20a80e..b7d5c11b3 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxConnectingFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxConnectingFragment.java
@@ -1,10 +1,15 @@
package org.briarproject.briar.android.mailbox;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.briar.R;
import org.briarproject.nullsafety.MethodsNotNullByDefault;
import org.briarproject.nullsafety.ParametersNotNullByDefault;
@@ -12,25 +17,71 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
+import static org.briarproject.briar.android.util.UiUtils.formatDuration;
+
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class MailboxConnectingFragment extends Fragment {
static final String TAG = MailboxConnectingFragment.class.getName();
+ private static final String ARG_STARTED = "started";
+ private static final long TIMEOUT_MS = TorConstants.EXTRA_CONNECT_TIMEOUT;
+ private static final long REFRESH_INTERVAL_MS = 1_000;
+
+ private final Handler handler = new Handler(Looper.getMainLooper());
+ // Capture a method reference so we use the same reference for posting
+ // and removing
+ private final Runnable refresher = this::updateProgressBar;
+
+ private ProgressBar progressBar;
+ private long timeStarted;
+
+ public static MailboxConnectingFragment newInstance(long timeStarted) {
+ MailboxConnectingFragment f = new MailboxConnectingFragment();
+ Bundle args = new Bundle();
+ args.putLong(ARG_STARTED, timeStarted);
+ f.setArguments(args);
+ return f;
+ }
+
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
- return inflater.inflate(R.layout.fragment_mailbox_connecting,
+ View v = inflater.inflate(R.layout.fragment_mailbox_connecting,
container, false);
+
+ progressBar = v.findViewById(R.id.progressBar);
+ TextView info = v.findViewById(R.id.info);
+ String duration = formatDuration(requireContext(), TIMEOUT_MS);
+ info.setText(getString(R.string.mailbox_setup_connecting_info,
+ duration));
+
+ timeStarted = requireArguments().getLong(ARG_STARTED);
+
+ return v;
}
@Override
public void onStart() {
super.onStart();
requireActivity().setTitle(R.string.mailbox_setup_title);
+ updateProgressBar();
}
+ @Override
+ public void onStop() {
+ super.onStop();
+ handler.removeCallbacks(refresher);
+ }
+
+ private void updateProgressBar() {
+ long elapsedMs = System.currentTimeMillis() - timeStarted;
+ int percent = (int) (elapsedMs * 100 / TIMEOUT_MS);
+ percent = Math.min(Math.max(percent, 0), 100);
+ progressBar.setProgress(percent);
+ handler.postDelayed(refresher, REFRESH_INTERVAL_MS);
+ }
}
diff --git a/briar-android/src/main/res/layout/fragment_mailbox_connecting.xml b/briar-android/src/main/res/layout/fragment_mailbox_connecting.xml
index c7cf2b242..3f285764b 100644
--- a/briar-android/src/main/res/layout/fragment_mailbox_connecting.xml
+++ b/briar-android/src/main/res/layout/fragment_mailbox_connecting.xml
@@ -1,31 +1,51 @@
-
-
+
+
+ app:layout_constraintTop_toBottomOf="@+id/progressBar"
+ tools:text="This may take up to 2 minutes" />
diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml
index 5e00eac0a..ad57f0bc6 100644
--- a/briar-android/src/main/res/values/strings.xml
+++ b/briar-android/src/main/res/values/strings.xml
@@ -633,7 +633,9 @@
Share Download Link
Scan Mailbox QR code
You have denied access to the camera, but scanning a QR code requires using the camera.\n\nPlease consider granting access.
- Connecting…
+ Connecting to Mailbox…
+
+ This may take up to %1s
Wrong QR code
The scanned code is invalid. Please open the Briar Mailbox app on your Mailbox device and scan the QR code it presents.
Mailbox already linked