mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Merge branch '1224-show-explanation-when-contact-exchange-fails' into 'master'
Show an error fragment when contact exchange fails See merge request briar/briar!890
This commit is contained in:
@@ -27,6 +27,7 @@ import org.briarproject.briar.android.introduction.ContactChooserFragment;
|
||||
import org.briarproject.briar.android.introduction.IntroductionActivity;
|
||||
import org.briarproject.briar.android.introduction.IntroductionMessageFragment;
|
||||
import org.briarproject.briar.android.keyagreement.ContactExchangeActivity;
|
||||
import org.briarproject.briar.android.keyagreement.ContactExchangeErrorFragment;
|
||||
import org.briarproject.briar.android.keyagreement.IntroFragment;
|
||||
import org.briarproject.briar.android.keyagreement.KeyAgreementActivity;
|
||||
import org.briarproject.briar.android.keyagreement.KeyAgreementFragment;
|
||||
@@ -208,4 +209,6 @@ public interface ActivityComponent {
|
||||
void inject(SettingsFragment fragment);
|
||||
|
||||
void inject(ScreenFilterDialogFragment fragment);
|
||||
|
||||
void inject(ContactExchangeErrorFragment fragment);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.R.string;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
@@ -48,7 +47,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle state) {
|
||||
super.onCreate(state);
|
||||
getSupportActionBar().setTitle(string.add_contact_title);
|
||||
getSupportActionBar().setTitle(R.string.add_contact_title);
|
||||
}
|
||||
|
||||
private void startContactExchange(KeyAgreementResult result) {
|
||||
@@ -75,7 +74,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
|
||||
public void contactExchangeSucceeded(Author remoteAuthor) {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
String contactName = remoteAuthor.getName();
|
||||
String format = getString(string.contact_added_toast);
|
||||
String format = getString(R.string.contact_added_toast);
|
||||
String text = String.format(format, contactName);
|
||||
Toast.makeText(ContactExchangeActivity.this, text, LENGTH_LONG)
|
||||
.show();
|
||||
@@ -87,7 +86,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
|
||||
public void duplicateContact(Author remoteAuthor) {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
String contactName = remoteAuthor.getName();
|
||||
String format = getString(string.contact_already_exists);
|
||||
String format = getString(R.string.contact_already_exists);
|
||||
String text = String.format(format, contactName);
|
||||
Toast.makeText(ContactExchangeActivity.this, text, LENGTH_LONG)
|
||||
.show();
|
||||
@@ -98,18 +97,14 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
|
||||
@Override
|
||||
public void contactExchangeFailed() {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
Toast.makeText(ContactExchangeActivity.this,
|
||||
string.contact_exchange_failed, LENGTH_LONG).show();
|
||||
finish();
|
||||
showErrorFragment(R.string.connection_error_explanation);
|
||||
});
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@Override
|
||||
public void keyAgreementFailed() {
|
||||
// TODO show failure somewhere persistent?
|
||||
Toast.makeText(this, R.string.connection_failed,
|
||||
LENGTH_LONG).show();
|
||||
showErrorFragment(R.string.connection_error_explanation);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@@ -126,19 +121,14 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
|
||||
|
||||
@UiThread
|
||||
@Override
|
||||
public String keyAgreementAborted(boolean remoteAborted) {
|
||||
// TODO show abort somewhere persistent?
|
||||
Toast.makeText(this,
|
||||
remoteAborted ? R.string.connection_aborted_remote :
|
||||
R.string.connection_aborted_local, LENGTH_LONG)
|
||||
.show();
|
||||
return null;
|
||||
public void keyAgreementAborted(boolean remoteAborted) {
|
||||
showErrorFragment(R.string.connection_error_explanation);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@Override
|
||||
public String keyAgreementFinished(KeyAgreementResult result) {
|
||||
startContactExchange(result);
|
||||
return getString(string.exchanging_contact_details);
|
||||
return getString(R.string.exchanging_contact_details);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.briarproject.briar.android.keyagreement;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.briar.android.util.UiUtils.onSingleLinkClick;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class ContactExchangeErrorFragment extends BaseFragment {
|
||||
|
||||
public static final String TAG =
|
||||
ContactExchangeErrorFragment.class.getName();
|
||||
private static final String ERROR_MSG = "errorMessage";
|
||||
|
||||
public static ContactExchangeErrorFragment newInstance(String errorMsg) {
|
||||
ContactExchangeErrorFragment f = new ContactExchangeErrorFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ERROR_MSG, errorMsg);
|
||||
f.setArguments(args);
|
||||
return f;
|
||||
}
|
||||
|
||||
@Inject
|
||||
AndroidExecutor androidExecutor;
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_error_contact_exchange,
|
||||
container, false);
|
||||
|
||||
// set humanized error message
|
||||
TextView explanation = v.findViewById(R.id.errorMessage);
|
||||
Bundle args = getArguments();
|
||||
if (args == null) {
|
||||
throw new IllegalArgumentException("Use newInstance()");
|
||||
}
|
||||
explanation.setText(args.getString(ERROR_MSG));
|
||||
|
||||
// make feedback link clickable
|
||||
TextView sendFeedback = v.findViewById(R.id.sendFeedback);
|
||||
onSingleLinkClick(sendFeedback, this::triggerFeedback);
|
||||
|
||||
// buttons
|
||||
Button tryAgain = v.findViewById(R.id.tryAgainButton);
|
||||
tryAgain.setOnClickListener(view -> {
|
||||
if (getActivity() != null) getActivity().onBackPressed();
|
||||
});
|
||||
Button cancel = v.findViewById(R.id.cancelButton);
|
||||
cancel.setOnClickListener(view -> finish());
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
private void triggerFeedback() {
|
||||
finish();
|
||||
UiUtils.triggerFeedback(androidExecutor);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
@@ -28,6 +29,7 @@ import org.briarproject.briar.android.activity.BriarActivity;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
|
||||
import org.briarproject.briar.android.keyagreement.IntroFragment.IntroScreenSeenListener;
|
||||
import org.briarproject.briar.android.keyagreement.KeyAgreementFragment.KeyAgreementEventListener;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
@@ -50,7 +52,7 @@ import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMI
|
||||
@ParametersNotNullByDefault
|
||||
public abstract class KeyAgreementActivity extends BriarActivity implements
|
||||
BaseFragmentListener, IntroScreenSeenListener,
|
||||
KeyAgreementFragment.KeyAgreementEventListener {
|
||||
KeyAgreementEventListener {
|
||||
|
||||
private enum BluetoothState {
|
||||
UNKNOWN, NO_ADAPTER, WAITING, REFUSED, ENABLED
|
||||
@@ -185,6 +187,12 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
||||
}
|
||||
}
|
||||
|
||||
protected void showErrorFragment(@StringRes int errorResId) {
|
||||
String errorMsg = getString(errorResId);
|
||||
BaseFragment f = ContactExchangeErrorFragment.newInstance(errorMsg);
|
||||
showNextFragment(f);
|
||||
}
|
||||
|
||||
private boolean checkPermissions() {
|
||||
if (ContextCompat.checkSelfPermission(this, CAMERA) !=
|
||||
PERMISSION_GRANTED) {
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.fragment.BaseEventFragment;
|
||||
import org.briarproject.briar.android.fragment.ErrorFragment;
|
||||
import org.briarproject.briar.android.view.QrCodeView;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -247,7 +246,7 @@ public class KeyAgreementFragment extends BaseEventFragment
|
||||
reset();
|
||||
String msg = getString(R.string.qr_code_unsupported,
|
||||
getString(R.string.app_name));
|
||||
showNextFragment(ErrorFragment.newInstance(msg));
|
||||
showNextFragment(ContactExchangeErrorFragment.newInstance(msg));
|
||||
} catch (CameraException e) {
|
||||
logCameraExceptionAndFinish(e);
|
||||
} catch (IOException | IllegalArgumentException e) {
|
||||
@@ -301,9 +300,7 @@ public class KeyAgreementFragment extends BaseEventFragment
|
||||
private void keyAgreementAborted(boolean remoteAborted) {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
reset();
|
||||
qrCodeView.setVisibility(VISIBLE);
|
||||
statusView.setVisibility(INVISIBLE);
|
||||
status.setText(listener.keyAgreementAborted(remoteAborted));
|
||||
listener.keyAgreementAborted(remoteAborted);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -362,10 +359,9 @@ public class KeyAgreementFragment extends BaseEventFragment
|
||||
@Nullable
|
||||
String keyAgreementStarted();
|
||||
|
||||
// Should return a string to be displayed as status.
|
||||
// Will show an error fragment.
|
||||
@UiThread
|
||||
@Nullable
|
||||
String keyAgreementAborted(boolean remoteAborted);
|
||||
void keyAgreementAborted(boolean remoteAborted);
|
||||
|
||||
// Should return a string to be displayed as status.
|
||||
@UiThread
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.acra.ACRA;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
@@ -43,7 +42,6 @@ import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.Localizer;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
import org.briarproject.briar.android.util.UserFeedback;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -86,6 +84,7 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_RINGTONE;
|
||||
import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_SIGN_OUT;
|
||||
import static org.briarproject.briar.android.util.UiUtils.hasScreenLock;
|
||||
import static org.briarproject.briar.android.util.UiUtils.triggerFeedback;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.BLOG_CHANNEL_ID;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.CONTACT_CHANNEL_ID;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.FORUM_CHANNEL_ID;
|
||||
@@ -219,7 +218,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
|
||||
findPreference("pref_key_send_feedback").setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
triggerFeedback();
|
||||
triggerFeedback(androidExecutor);
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -517,11 +516,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
return true;
|
||||
}
|
||||
|
||||
private void triggerFeedback() {
|
||||
androidExecutor.runOnBackgroundThread(() -> ACRA.getErrorReporter()
|
||||
.handleException(new UserFeedback(), false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (preference == language) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.format.DateUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.URLSpan;
|
||||
@@ -28,9 +29,11 @@ import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.acra.ACRA;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.view.ArticleMovementMethod;
|
||||
import org.briarproject.briar.android.widget.LinkDialogFragment;
|
||||
@@ -147,6 +150,32 @@ public class UiUtils {
|
||||
v.setMovementMethod(ArticleMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the runnable when clicking the link in the textView's text.
|
||||
*
|
||||
* Attention: This assumes that there's only <b>one</b> link in the text.
|
||||
*/
|
||||
public static void onSingleLinkClick(TextView textView, Runnable runnable) {
|
||||
SpannableStringBuilder ssb =
|
||||
new SpannableStringBuilder(textView.getText());
|
||||
ClickableSpan[] spans =
|
||||
ssb.getSpans(0, ssb.length(), ClickableSpan.class);
|
||||
if (spans.length != 1) throw new AssertionError();
|
||||
ClickableSpan span = spans[0];
|
||||
int start = ssb.getSpanStart(span);
|
||||
int end = ssb.getSpanEnd(span);
|
||||
ssb.removeSpan(span);
|
||||
ClickableSpan cSpan = new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
runnable.run();
|
||||
}
|
||||
};
|
||||
ssb.setSpan(cSpan, start + 1, end, 0);
|
||||
textView.setText(ssb);
|
||||
textView.setMovementMethod(new LinkMovementMethod());
|
||||
}
|
||||
|
||||
public static String getAvatarTransitionName(ContactId c) {
|
||||
return "avatar" + c.getInt();
|
||||
}
|
||||
@@ -242,4 +271,10 @@ public class UiUtils {
|
||||
(SDK_INT >= 23 && keyguardManager.isDeviceSecure());
|
||||
}
|
||||
|
||||
public static void triggerFeedback(AndroidExecutor androidExecutor) {
|
||||
androidExecutor.runOnBackgroundThread(
|
||||
() -> ACRA.getErrorReporter()
|
||||
.handleException(new UserFeedback(), false));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
23
briar-android/src/main/res/drawable/qr_code_error.xml
Normal file
23
briar-android/src/main/res/drawable/qr_code_error.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="409.2dp"
|
||||
android:height="161.7dp"
|
||||
android:viewportHeight="161.7"
|
||||
android:viewportWidth="409.2">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M369.8,157.4l-4.3,-4.3l-7.1,-2.4c-3.9,-1.3 -8.7,-3 -10.7,-3.7l-3.7,-1.3l3.5,-0.2c8.2,-0.4 13,-4 14.3,-10.9c0.8,-4.1 1.1,-17.3 0.8,-33c-0.2,-8.1 -0.2,-15.4 0,-16.3c0.1,-0.9 0.5,-2.4 0.9,-3.4c1.2,-3.5 0.3,-11.9 -1.9,-17.6c-0.3,-0.9 -1.9,-4.2 -3.5,-7.4c-4.2,-8.2 -4.5,-8.9 -4.9,-10.5c-0.5,-1.8 -0.2,-5.4 0.5,-6.8c0.7,-1.3 2.2,-2.9 3.2,-3.5c1.3,-0.7 2.6,0.1 4.7,2.9c3.4,4.5 14,19.4 15.7,22.2c3.7,6 6,11.2 8,18.8c0.7,2.5 1.9,7 2.7,10.1c0.8,3.1 2.7,10.2 4.1,15.8l2.6,10.2l4.6,5.2c2.6,2.9 5.8,6.5 7.2,8c1.4,1.6 2.5,3 2.5,3.2c0,0.3 -34.5,29.3 -34.9,29.3C374.2,161.7 372.2,159.7 369.8,157.4zM275.9,141c-1.3,-0.6 -2.2,-1.4 -2.9,-2.3c-2.1,-2.7 -2,2.4 -1.9,-68.5l0.1,-64l0.7,-1.2c1,-1.9 2,-2.9 3.7,-3.9l1.6,-0.9l37.8,-0.1c42.5,-0.1 39.4,-0.2 42.1,2.2c0.9,0.8 1.8,2 2.2,2.9c0.7,1.6 0.7,1.6 0.8,14.2l0.1,12.6l-1.8,-0.1c-1.4,-0.1 -2.1,0 -3.2,0.5c-2,1 -3.9,2.9 -5.1,5.1l-1,2l0,-12.8l0,-12.8h-33.6h-33.6v51.3v51.3h33.6h33.6l0.1,-34.4c0.1,-33 0.1,-34.4 0.6,-32.9c0.3,0.8 1.8,4 3.4,7c5.5,10.6 5.4,9.9 5.4,47.2c0,27.6 -0.1,30 -1.7,33.1c-1.1,2.2 -2.7,3.7 -5.1,4.7l-1.7,0.7L314,141.8l-36.2,0.1L275.9,141L275.9,141zM318.3,135.9c2.9,-1.3 4.5,-3.7 4.4,-6.6c0,-4.1 -3.1,-7.2 -7.1,-7.2c-2.1,0 -3.6,0.6 -5.2,2.2c-2.2,2.2 -2.8,5.4 -1.3,8.3c0.7,1.4 2.5,3 4,3.5C314.6,136.6 317,136.6 318.3,135.9z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M39.4,157.4l4.3,-4.3l7.1,-2.4c3.9,-1.3 8.7,-3 10.7,-3.7l3.7,-1.3l-3.5,-0.2c-8.2,-0.4 -13,-4 -14.3,-10.9c-0.8,-4.1 -1.1,-17.3 -0.8,-33c0.2,-8.1 0.2,-15.4 0,-16.3c-0.1,-0.9 -0.5,-2.4 -0.9,-3.4c-1.2,-3.5 -0.3,-11.9 1.9,-17.6c0.3,-0.9 1.9,-4.2 3.5,-7.4c4.2,-8.2 4.5,-8.9 4.9,-10.5c0.5,-1.8 0.2,-5.4 -0.5,-6.8c-0.7,-1.3 -2.2,-2.9 -3.2,-3.5c-1.3,-0.7 -2.6,0.1 -4.7,2.9c-3.4,4.5 -14,19.4 -15.7,22.2c-3.7,6 -6,11.2 -8,18.8c-0.7,2.5 -1.9,7 -2.7,10.1c-0.8,3.1 -2.7,10.2 -4.1,15.8l-2.6,10.2l-4.6,5.2c-2.6,2.9 -5.8,6.5 -7.2,8s-2.5,3 -2.5,3.2c0,0.3 34.5,29.3 34.9,29.3C35,161.7 37.1,159.7 39.4,157.4zM133.3,141c1.3,-0.6 2.2,-1.4 2.9,-2.3c2.1,-2.7 2,2.4 1.9,-68.5l-0.1,-64l-0.7,-1.2c-1,-1.9 -2,-2.9 -3.7,-3.9l-1.6,-0.9l-37.8,-0.1c-42.5,-0.1 -39.4,-0.2 -42.1,2.2c-0.9,0.8 -1.8,2 -2.2,2.9c-0.7,1.6 -0.7,1.6 -0.8,14.2L49,32l1.8,-0.1c1.4,-0.1 2.1,0 3.2,0.5c2,1 3.9,2.9 5.1,5.1l1,2l0,-12.8l0,-12.8h33.6h33.6v51.3v51.3L93.8,116.5L60.2,116.5l-0.1,-34.4c-0.1,-33 -0.1,-34.4 -0.6,-32.9c-0.3,0.8 -1.8,4 -3.4,7c-5.5,10.6 -5.4,9.9 -5.4,47.2c0,27.6 0.1,30 1.7,33.1c1.1,2.2 2.7,3.7 5.1,4.7l1.7,0.7l36.2,0.1l36.2,0.1L133.3,141L133.3,141zM90.9,135.9c-2.9,-1.3 -4.5,-3.7 -4.4,-6.6c0,-4.1 3.1,-7.2 7.1,-7.2c2.1,0 3.6,0.6 5.2,2.2c2.2,2.2 2.8,5.4 1.3,8.3c-0.7,1.4 -2.5,3 -4,3.5C94.6,136.6 92.3,136.6 90.9,135.9z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M80.5,63h2.3v2.3h2.3v2.3L73.6,67.6v-2.3h2.3v-4.6h4.6L80.5,63L80.5,63zM110.5,83.8h2.3v-2.3h-2.3L110.5,83.8zM82.8,63h2.3v-2.3h-2.3L82.8,63zM115.1,83.8h2.3v-2.3h-2.3L115.1,83.8zM87.4,86.1L92,86.1L92,83.8h-4.6L87.4,86.1zM108.2,86.1L108.2,83.8h-2.3v2.3L108.2,86.1zM99,86.1h2.3v-4.6L99,81.5L99,86.1zM80.5,56.1v2.3h6.9v-2.3L80.5,56.1zM78.2,58.4v-2.3h-4.6v4.6h2.3v-2.3L78.2,58.4zM85.1,53.8L69,53.8v-16.1h16.1L85.1,53.8zM82.8,40L71.3,40v11.5h11.5L82.8,40zM73.6,81.5h6.9v-6.9h-6.9L73.6,81.5zM96.6,79.1v2.3L99,81.4v-2.3L96.6,79.1zM80.5,42.3h-6.9v6.9h6.9L80.5,42.3zM117.4,37.7L117.4,53.8L101.3,53.8v-16.1L117.4,37.7zM115.1,40L103.6,40v11.5h11.5L115.1,40zM69,69.9h16.1v16.1L69,86L69,69.9zM71.3,83.8h11.5v-11.5L71.3,72.3L71.3,83.8zM71.3,56.1L69,56.1v11.5h2.3L71.3,56.1zM101.3,67.6v2.3h2.3v-2.3L101.3,67.6zM94.3,76.9v-2.3L92,74.6v2.3h-4.6v4.6L92,81.5v2.3h2.3v-4.6h2.3v-2.3L94.3,76.9zM87.4,46.9L92,46.9v-2.3h-4.6L87.4,46.9zM105.9,65.3h4.6v2.3h2.3v-6.9h-2.3v-4.6h-2.3v6.9h-6.9v2.3h2.3v2.3h2.3L105.9,65.3zM108.2,72.2h-2.3v-2.3h-2.3v4.6h-6.9v2.3h4.6v4.6h2.3v2.3h2.3v-4.6h9.2v-2.3h-6.9L108.2,72.2zM108.2,72.2h2.3v-4.6h-2.3L108.2,72.2zM89.7,72.2v-2.3L92,69.9v-2.3h2.3v-2.3h2.3v-4.6h6.9v-4.6h-2.3v2.3L99,58.4v-9.2h-2.3v-4.6L99,44.6v-6.9h-2.3v4.6h-2.3v-4.6h-6.9v4.6h2.3v-2.3L92,40v4.6h2.3v6.9h2.3v2.3h-2.3v4.6L92,58.4L92,53.8h-2.3v-2.3h-2.3v4.6h2.3v2.3h-2.3v6.9h2.3v-4.6L92,60.7v4.6h-2.3v2.3h-2.3v6.9L92,74.5v-2.3L89.7,72.2zM115.1,74.5v-2.3h-4.6v2.3L115.1,74.5zM112.8,42.3h-6.9v6.9h6.9L112.8,42.3zM94.3,72.2L99,72.2v-2.3h-2.3v-2.3h-2.3L94.4,72.2zM99,67.6v-2.3h-2.3v2.3L99,67.6zM112.8,58.4h4.6v-2.3h-4.6L112.8,58.4zM115.1,76.9h2.3v-2.3h-2.3L115.1,76.9zM115.1,63h2.3v-2.3h-2.3L115.1,63zM94.3,51.5L92,51.5v2.3h2.3L94.3,51.5zM94.3,51.5"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M303.5,63h2.3v2.3h2.3v2.3h-11.5v-2.3h2.3v-4.6h4.6L303.5,63L303.5,63zM333.5,83.8h2.3v-2.3h-2.3L333.5,83.8zM305.8,63h2.3v-2.3h-2.3L305.8,63zM338.1,83.8h2.3v-2.3h-2.3L338.1,83.8zM310.4,86.1h4.6L315,83.8h-4.6L310.4,86.1zM331.2,86.1L331.2,83.8h-2.3v2.3L331.2,86.1zM322,86.1h2.3v-4.6L322,81.5L322,86.1zM303.5,56.1v2.3h6.9v-2.3L303.5,56.1zM301.2,58.4v-2.3h-4.6v4.6h2.3v-2.3L301.2,58.4zM308.1,53.8L292,53.8v-16.1h16.1L308.1,53.8zM305.8,40h-11.5v11.5h11.5L305.8,40zM296.6,81.5h6.9v-6.9h-6.9L296.6,81.5zM319.6,79.1v2.3h2.3v-2.3L319.6,79.1zM303.5,42.3h-6.9v6.9h6.9L303.5,42.3zM340.4,37.7L340.4,53.8h-16.1v-16.1L340.4,37.7zM338.1,40h-11.5v11.5h11.5L338.1,40zM292,69.9h16.1v16.1L292,86L292,69.9zM294.3,83.8h11.5v-11.5h-11.5L294.3,83.8zM294.3,56.1L292,56.1v11.5h2.3L294.3,56.1zM324.3,67.6v2.3h2.3v-2.3L324.3,67.6zM317.3,76.9v-2.3L315,74.6v2.3h-4.6v4.6h4.6v2.3h2.3v-4.6h2.3v-2.3L317.3,76.9zM310.4,46.9h4.6v-2.3h-4.6L310.4,46.9zM328.9,65.3h4.6v2.3h2.3v-6.9h-2.3v-4.6h-2.3v6.9h-6.9v2.3h2.3v2.3h2.3L328.9,65.3zM331.2,72.2h-2.3v-2.3h-2.3v4.6h-6.9v2.3h4.6v4.6h2.3v2.3h2.3v-4.6h9.2v-2.3h-6.9L331.2,72.2zM331.2,72.2h2.3v-4.6h-2.3L331.2,72.2zM312.7,72.2v-2.3h2.3v-2.3h2.3v-2.3h2.3v-4.6h6.9v-4.6h-2.3v2.3L322,58.4v-9.2h-2.3v-4.6h2.3v-6.9h-2.3v4.6h-2.3v-4.6h-6.9v4.6h2.3v-2.3h2.3v4.6h2.3v6.9h2.3v2.3h-2.3v4.6L315,58.4L315,53.8h-2.3v-2.3h-2.3v4.6h2.3v2.3h-2.3v6.9h2.3v-4.6h2.3v4.6h-2.3v2.3h-2.3v6.9h4.6v-2.3L312.7,72.2zM338.1,74.5v-2.3h-4.6v2.3L338.1,74.5zM335.8,42.3h-6.9v6.9h6.9L335.8,42.3zM317.3,72.2h4.6v-2.3h-2.3v-2.3h-2.3L317.3,72.2zM322,67.6v-2.3h-2.3v2.3L322,67.6zM335.8,58.4h4.6v-2.3h-4.6L335.8,58.4zM338.1,76.9h2.3v-2.3h-2.3L338.1,76.9zM338.1,63h2.3v-2.3h-2.3L338.1,63zM317.3,51.5L315,51.5v2.3h2.3L317.3,51.5zM317.3,51.5"/>
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M 207.61295,88.782357 h -6.42588 v -12.85177 h 6.42588 m 0,25.703533 h -6.42588 v -6.425883 h 6.42588 m -38.5553,16.064713 h 70.68472 L 204.40001,50.227047 Z"
|
||||
android:strokeWidth="3.21294165"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/errorTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/connection_error_title"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_large"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/errorIcon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/qr_code_error"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/errorTitle"
|
||||
app:tint="?attr/colorControlNormal"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/errorMessage"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
app:layout_constraintBottom_toTopOf="@+id/sendFeedback"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/errorIcon"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="@string/connection_error_explanation"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sendFeedback"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/connection_error_feedback"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
app:layout_constraintBottom_toTopOf="@+id/tryAgainButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/errorMessage"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/tryAgainButton"
|
||||
style="@style/BriarButtonFlat.Positive"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:text="@string/try_again_button"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toEndOf="@+id/cancelButton"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancelButton"
|
||||
style="@style/BriarButtonFlat.Negative"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="@string/cancel"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/tryAgainButton"
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</ScrollView>
|
||||
@@ -135,20 +135,19 @@
|
||||
<string name="add_contact_title">Add a Contact</string>
|
||||
<string name="face_to_face">You must meet up with the person you want to add as a contact.\n\nThis will prevent anyone from impersonating you or reading your messages in future.</string>
|
||||
<string name="continue_button">Continue</string>
|
||||
<string name="connection_failed">Connection failed</string>
|
||||
<string name="try_again_button">Try Again</string>
|
||||
<string name="waiting_for_contact_to_scan">Waiting for contact to scan and connect\u2026</string>
|
||||
<string name="exchanging_contact_details">Exchanging contact details\u2026</string>
|
||||
<string name="contact_added_toast">Contact added: %s</string>
|
||||
<string name="contact_already_exists">Contact %s already exists</string>
|
||||
<string name="contact_exchange_failed">Contact exchange failed</string>
|
||||
<string name="qr_code_invalid">The QR code is invalid</string>
|
||||
<string name="qr_code_unsupported">The QR code you are trying to scan belongs to an old version of %s which is no longer supported.\n\nPlease ensure that both of you are running the latest version and then try again.</string>
|
||||
<string name="camera_error">Camera error</string>
|
||||
<string name="connecting_to_device">Connecting to device\u2026</string>
|
||||
<string name="authenticating_with_device">Authenticating with device\u2026</string>
|
||||
<string name="connection_aborted_local">Connection aborted! This could mean that someone is trying to interfere with your connection</string>
|
||||
<string name="connection_aborted_remote">Connection aborted by your contact! This could mean that someone is trying to interfere with your connection</string>
|
||||
<string name="connection_error_title">Could not connect to your contact</string>
|
||||
<string name="connection_error_explanation">Please check that you\'re both connected to the same Wi-Fi network.</string>
|
||||
<string name="connection_error_feedback">If this problem persists, please <a href="feedback">send feedback</a> to help us improve the app.</string>
|
||||
|
||||
<!-- Introductions -->
|
||||
<string name="introduction_onboarding_title">Introduce your contacts</string>
|
||||
|
||||
Reference in New Issue
Block a user