Only offer share/compare options when SN calculation is complete

Now that we're loading this asynchronously, these options need
to respond asynchronously as well

Fixes #6739
// FREEBIE
This commit is contained in:
Moxie Marlinspike 2017-06-19 10:39:15 -07:00
parent 8208bbf3c0
commit 0cc5618ba9

View File

@ -35,8 +35,6 @@ import android.os.Vibrator;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi; import android.support.annotation.RequiresApi;
import android.support.v4.animation.AnimatorCompatHelper;
import android.support.v4.animation.ValueAnimatorCompat;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction; import android.support.v4.app.FragmentTransaction;
import android.support.v7.widget.SwitchCompat; import android.support.v7.widget.SwitchCompat;
@ -147,22 +145,10 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
} }
} }
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.clear();
MenuInflater inflater = this.getMenuInflater();
inflater.inflate(R.menu.verify_identity, menu);
return true;
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.verify_identity__share: handleShare(); return true; case android.R.id.home: finish(); return true;
case android.R.id.home: finish(); return true;
} }
return false; return false;
@ -210,24 +196,6 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
} }
} }
private void handleShare() {
String shareString =
getString(R.string.VerifyIdentityActivity_our_signal_safety_number) + "\n" +
displayFragment.getFormattedSafetyNumbers() + "\n";
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, shareString);
intent.setType("text/plain");
try {
startActivity(Intent.createChooser(intent, getString(R.string.VerifyIdentityActivity_share_safety_number_via)));
} catch (ActivityNotFoundException e) {
Toast.makeText(VerifyIdentityActivity.this, R.string.VerifyIdentityActivity_no_app_to_share_to, Toast.LENGTH_LONG).show();
}
}
public static class VerifyDisplayFragment extends Fragment implements Recipient.RecipientModifiedListener, CompoundButton.OnCheckedChangeListener { public static class VerifyDisplayFragment extends Fragment implements Recipient.RecipientModifiedListener, CompoundButton.OnCheckedChangeListener {
public static final String REMOTE_RECIPIENT_ID = "remote_recipient_id"; public static final String REMOTE_RECIPIENT_ID = "remote_recipient_id";
@ -314,10 +282,12 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
@Override @Override
protected void onPostExecute(Fingerprint fingerprint) { protected void onPostExecute(Fingerprint fingerprint) {
VerifyDisplayFragment.this.fingerprint = fingerprint; VerifyDisplayFragment.this.fingerprint = fingerprint;
setFingerprintViews(fingerprint, true); setFingerprintViews(fingerprint, true);
getActivity().supportInvalidateOptionsMenu();
} }
}.execute(); }.execute();
setHasOptionsMenu(true);
} }
@Override @Override
@ -345,7 +315,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
animateVerifiedSuccess(); animateVerifiedSuccess();
} else if (animateFailureOnDraw) { } else if (animateFailureOnDraw) {
animateFailureOnDraw = false; animateFailureOnDraw = false;
animateVerifiedFailure();; animateVerifiedFailure();
} }
} }
@ -361,20 +331,41 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
{ {
super.onCreateContextMenu(menu, view, menuInfo); super.onCreateContextMenu(menu, view, menuInfo);
MenuInflater inflater = getActivity().getMenuInflater(); if (fingerprint != null) {
inflater.inflate(R.menu.verify_display_fragment_context_menu, menu); MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.verify_display_fragment_context_menu, menu);
}
} }
@Override @Override
public boolean onContextItemSelected(MenuItem item) { public boolean onContextItemSelected(MenuItem item) {
if (fingerprint == null) return super.onContextItemSelected(item);
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.menu_copy: handleCopyToClipboard(); return true; case R.id.menu_copy: handleCopyToClipboard(fingerprint, codes.length); return true;
case R.id.menu_compare: handleCompareWithClipboard(); return true; case R.id.menu_compare: handleCompareWithClipboard(fingerprint); return true;
default: return super.onContextItemSelected(item); default: return super.onContextItemSelected(item);
} }
} }
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
if (fingerprint != null) {
inflater.inflate(R.menu.verify_identity, menu);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.verify_identity__share: handleShare(fingerprint, codes.length); return true;
}
return false;
}
public void setScannedFingerprint(String scanned) { public void setScannedFingerprint(String scanned) {
try { try {
if (fingerprint.getScannableFingerprint().compareTo(scanned.getBytes("ISO-8859-1"))) { if (fingerprint.getScannableFingerprint().compareTo(scanned.getBytes("ISO-8859-1"))) {
@ -401,13 +392,14 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
this.clickListener = listener; this.clickListener = listener;
} }
public String getFormattedSafetyNumbers() { private @NonNull String getFormattedSafetyNumbers(@NonNull Fingerprint fingerprint, int segmentCount) {
StringBuilder result = new StringBuilder(); String[] segments = getSegments(fingerprint, segmentCount);
StringBuilder result = new StringBuilder();
for (int i = 0; i < codes.length; i++) { for (int i = 0; i < segments.length; i++) {
result.append(codes[i].getText()); result.append(segments[i]);
if (i != codes.length - 1) { if (i != segments.length - 1) {
if (((i+1) % 4) == 0) result.append('\n'); if (((i+1) % 4) == 0) result.append('\n');
else result.append(' '); else result.append(' ');
} }
@ -416,11 +408,11 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
return result.toString(); return result.toString();
} }
private void handleCopyToClipboard() { private void handleCopyToClipboard(Fingerprint fingerprint, int segmentCount) {
Util.writeTextToClipboard(getActivity(), getFormattedSafetyNumbers()); Util.writeTextToClipboard(getActivity(), getFormattedSafetyNumbers(fingerprint, segmentCount));
} }
private void handleCompareWithClipboard() { private void handleCompareWithClipboard(Fingerprint fingerprint) {
String clipboardData = Util.readTextFromClipboard(getActivity()); String clipboardData = Util.readTextFromClipboard(getActivity());
if (clipboardData == null) { if (clipboardData == null) {
@ -442,19 +434,34 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
} }
} }
private void handleShare(@NonNull Fingerprint fingerprint, int segmentCount) {
String shareString =
getString(R.string.VerifyIdentityActivity_our_signal_safety_number) + "\n" +
getFormattedSafetyNumbers(fingerprint, segmentCount) + "\n";
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, shareString);
intent.setType("text/plain");
try {
startActivity(Intent.createChooser(intent, getString(R.string.VerifyIdentityActivity_share_safety_number_via)));
} catch (ActivityNotFoundException e) {
Toast.makeText(getActivity(), R.string.VerifyIdentityActivity_no_app_to_share_to, Toast.LENGTH_LONG).show();
}
}
private void setRecipientText(Recipient recipient) { private void setRecipientText(Recipient recipient) {
description.setText(Html.fromHtml(String.format(getActivity().getString(R.string.verify_display_fragment__if_you_wish_to_verify_the_security_of_your_end_to_end_encryption_with_s), recipient.toShortString()))); description.setText(Html.fromHtml(String.format(getActivity().getString(R.string.verify_display_fragment__if_you_wish_to_verify_the_security_of_your_end_to_end_encryption_with_s), recipient.toShortString())));
description.setMovementMethod(LinkMovementMethod.getInstance()); description.setMovementMethod(LinkMovementMethod.getInstance());
} }
private void setFingerprintViews(Fingerprint fingerprint, boolean animate) { private void setFingerprintViews(Fingerprint fingerprint, boolean animate) {
String digits = fingerprint.getDisplayableFingerprint().getDisplayText(); String[] segments = getSegments(fingerprint, codes.length);
int partSize = digits.length() / codes.length;
for (int i=0;i<codes.length;i++) { for (int i=0;i<codes.length;i++) {
String substring = digits.substring(i * partSize, (i * partSize) + partSize); if (animate) setCodeSegment(codes[i], segments[i]);
if (animate) setCodeSegment(codes[i], substring); else codes[i].setText(segments[i]);
else codes[i].setText(substring);
} }
byte[] qrCodeData = fingerprint.getScannableFingerprint().getSerialized(); byte[] qrCodeData = fingerprint.getScannableFingerprint().getSerialized();
@ -499,6 +506,18 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
} }
} }
private String[] getSegments(Fingerprint fingerprint, int segmentCount) {
String[] segments = new String[segmentCount];
String digits = fingerprint.getDisplayableFingerprint().getDisplayText();
int partSize = digits.length() / segmentCount;
for (int i=0;i<segmentCount;i++) {
segments[i] = digits.substring(i * partSize, (i * partSize) + partSize);
}
return segments;
}
private Bitmap createVerifiedBitmap(int width, int height, @DrawableRes int id) { private Bitmap createVerifiedBitmap(int width, int height, @DrawableRes int id) {
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap); Canvas canvas = new Canvas(bitmap);