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/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..2e39696f9 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,48 @@ - + + + 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