Combine input and output into one screen.

This commit is contained in:
akwizgran
2018-09-28 15:34:17 +01:00
parent d8a9b03e2f
commit e7adfef6f7
15 changed files with 402 additions and 622 deletions

View File

@@ -415,14 +415,9 @@
<!-- Prototype --> <!-- Prototype -->
<activity <activity
android:name=".android.contact.ContactInviteOutputActivity" android:name=".android.contact.ContactLinkExchangeActivity"
android:theme="@style/BriarTheme" android:theme="@style/BriarTheme"
android:label="@string/send_link_title"/> android:label="@string/add_contact_title"
<activity
android:name=".android.contact.ContactInviteInputActivity"
android:theme="@style/BriarTheme"
android:label="@string/open_link_title"
android:windowSoftInputMode="stateHidden|adjustResize"> android:windowSoftInputMode="stateHidden|adjustResize">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />

View File

@@ -15,11 +15,8 @@ import org.briarproject.briar.android.blog.ReblogFragment;
import org.briarproject.briar.android.blog.RssFeedImportActivity; import org.briarproject.briar.android.blog.RssFeedImportActivity;
import org.briarproject.briar.android.blog.RssFeedManageActivity; import org.briarproject.briar.android.blog.RssFeedManageActivity;
import org.briarproject.briar.android.blog.WriteBlogPostActivity; import org.briarproject.briar.android.blog.WriteBlogPostActivity;
import org.briarproject.briar.android.contact.ContactAliasInputFragment; import org.briarproject.briar.android.contact.ContactLinkExchangeActivity;
import org.briarproject.briar.android.contact.ContactInviteInputActivity; import org.briarproject.briar.android.contact.ContactLinkExchangeFragment;
import org.briarproject.briar.android.contact.ContactInviteOutputActivity;
import org.briarproject.briar.android.contact.ContactLinkInputFragment;
import org.briarproject.briar.android.contact.ContactLinkOutputFragment;
import org.briarproject.briar.android.contact.ContactListFragment; import org.briarproject.briar.android.contact.ContactListFragment;
import org.briarproject.briar.android.contact.ContactModule; import org.briarproject.briar.android.contact.ContactModule;
import org.briarproject.briar.android.contact.ContactQrCodeInputFragment; import org.briarproject.briar.android.contact.ContactQrCodeInputFragment;
@@ -175,14 +172,9 @@ public interface ActivityComponent {
void inject(UnlockActivity activity); void inject(UnlockActivity activity);
void inject(ContactInviteOutputActivity activity); void inject(ContactLinkExchangeActivity activity);
void inject(ContactInviteInputActivity activity);
void inject(PendingRequestsActivity activity); void inject(PendingRequestsActivity activity);
void inject(ContactLinkOutputFragment activity);
void inject(ContactQrCodeOutputFragment activity);
void inject(ContactLinkInputFragment activity);
void inject(ContactQrCodeInputFragment activity);
void inject(ContactAliasInputFragment activity);
// Fragments // Fragments
void inject(AuthorNameFragment fragment); void inject(AuthorNameFragment fragment);
@@ -228,4 +220,11 @@ public interface ActivityComponent {
void inject(ScreenFilterDialogFragment fragment); void inject(ScreenFilterDialogFragment fragment);
void inject(ContactExchangeErrorFragment fragment); void inject(ContactExchangeErrorFragment fragment);
void inject(ContactLinkExchangeFragment fragment);
void inject(ContactQrCodeOutputFragment fragment);
void inject(ContactQrCodeInputFragment fragment);
} }

View File

@@ -1,116 +0,0 @@
package org.briarproject.briar.android.contact;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import javax.annotation.Nullable;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.Build.VERSION.SDK_INT;
import static org.briarproject.briar.android.util.UiUtils.resolveColorAttribute;
@NotNullByDefault
public class ContactAliasInputFragment extends BaseFragment
implements TextWatcher {
private EditText contactNameInput;
private Button addButton;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
getActivity().setTitle("Enter Contact Name");
View v = inflater.inflate(R.layout.fragment_contact_alias_input,
container, false);
contactNameInput = v.findViewById(R.id.contactNameInput);
contactNameInput.addTextChangedListener(this);
addButton = v.findViewById(R.id.addButton);
addButton.setOnClickListener(view -> onAddButtonClicked());
return v;
}
public static final String TAG = ContactAliasInputFragment.class.getName();
@Override
public String getUniqueTag() {
return TAG;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
updateAddButtonState();
}
@Override
public void afterTextChanged(Editable s) {
}
private boolean isBriarLink(CharSequence s) {
return getActivity() != null &&
((ContactInviteInputActivity) getActivity()).isBriarLink(s);
}
private void updateAddButtonState() {
addButton.setEnabled(contactNameInput.getText().length() > 0);
}
private void onAddButtonClicked() {
if (getActivity() == null || getContext() == null) return;;
((ContactInviteInputActivity) getActivity())
.addFakeRequest(contactNameInput.getText().toString());
AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), R.style.BriarDialogTheme_Neutral);
builder.setTitle("Contact requested");
builder.setMessage(getString(R.string.add_contact_link_question));
builder.setPositiveButton(R.string.yes, (dialog, which) -> {
Intent intent = new Intent(getContext(), NavDrawerActivity.class);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
});
builder.setNegativeButton(R.string.no, (dialog, which) -> {
startActivity(
new Intent(getContext(), ContactInviteOutputActivity.class));
finish();
});
builder.show();
}
}

View File

@@ -1,57 +0,0 @@
package org.briarproject.briar.android.contact;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.view.MenuItem;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
import javax.annotation.Nullable;
public class ContactInviteOutputActivity extends BriarActivity implements
BaseFragmentListener {
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@Override
public void onCreate(@Nullable Bundle state) {
super.onCreate(state);
setContentView(R.layout.activity_fragment_container);
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setDisplayHomeAsUpEnabled(true);
}
if (state == null) {
showInitialFragment(new ContactLinkOutputFragment());
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
void showLink() {
showInitialFragment(new ContactLinkOutputFragment());
}
void showCode() {
showNextFragment(new ContactQrCodeOutputFragment());
}
}

View File

@@ -5,7 +5,6 @@ import android.app.PendingIntent;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.util.Log;
import android.view.MenuItem; import android.view.MenuItem;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
@@ -17,7 +16,7 @@ import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener; import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
import org.briarproject.briar.api.messaging.MessagingManager; import org.briarproject.briar.api.messaging.MessagingManager;
import java.util.Random; import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
@@ -29,13 +28,17 @@ import static android.content.Intent.EXTRA_TEXT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.SystemClock.elapsedRealtime; import static android.os.SystemClock.elapsedRealtime;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
import static org.briarproject.bramble.util.LogUtils.logException;
public class ContactInviteInputActivity extends BriarActivity implements public class ContactLinkExchangeActivity extends BriarActivity implements
BaseFragmentListener { BaseFragmentListener {
private static final Logger LOG =
Logger.getLogger(ContactLinkExchangeActivity.class.getName());
@Inject @Inject
LifecycleManager lifecycleManager; LifecycleManager lifecycleManager;
@Inject @Inject
@@ -65,13 +68,13 @@ public class ContactInviteInputActivity extends BriarActivity implements
String text = i.getStringExtra(EXTRA_TEXT); String text = i.getStringExtra(EXTRA_TEXT);
if (text != null) { if (text != null) {
showInitialFragment( showInitialFragment(
ContactLinkInputFragment.newInstance(text)); ContactLinkExchangeFragment.newInstance(text));
return; return;
} }
String uri = i.getDataString(); String uri = i.getDataString();
if (uri != null) { if (uri != null) {
showInitialFragment( showInitialFragment(
ContactLinkInputFragment.newInstance(uri)); ContactLinkExchangeFragment.newInstance(uri));
return; return;
} }
} else if ("addContact".equals(action)) { } else if ("addContact".equals(action)) {
@@ -82,7 +85,7 @@ public class ContactInviteInputActivity extends BriarActivity implements
} }
} }
if (state == null) { if (state == null) {
showInitialFragment(ContactLinkInputFragment.newInstance(null)); showInitialFragment(new ContactLinkExchangeFragment());
} }
} }
@@ -102,16 +105,16 @@ public class ContactInviteInputActivity extends BriarActivity implements
return link.matches("^(briar://)?[a-z2-7]{64}$"); return link.matches("^(briar://)?[a-z2-7]{64}$");
} }
void showLink(@Nullable String link) { void scanCode() {
showInitialFragment(ContactLinkInputFragment.newInstance(link));
}
void showCode() {
showNextFragment(new ContactQrCodeInputFragment()); showNextFragment(new ContactQrCodeInputFragment());
} }
void showAlias() { void linkScanned(@Nullable String link) {
showNextFragment(new ContactAliasInputFragment()); showNextFragment(ContactLinkExchangeFragment.newInstance(link));
}
void showCode() {
showNextFragment(new ContactQrCodeOutputFragment());
} }
void addFakeRequest(String name) { void addFakeRequest(String name) {
@@ -119,40 +122,35 @@ public class ContactInviteInputActivity extends BriarActivity implements
try { try {
messagingManager.addNewPendingContact(name, timestamp); messagingManager.addNewPendingContact(name, timestamp);
} catch (DbException e) { } catch (DbException e) {
e.printStackTrace(); logException(LOG, WARNING, e);
} }
AlarmManager alarmManager = AlarmManager alarmManager =
(AlarmManager) requireNonNull(getSystemService(ALARM_SERVICE)); (AlarmManager) requireNonNull(getSystemService(ALARM_SERVICE));
long m = MINUTES.toMillis(1); long m = MINUTES.toMillis(1);
long fromNow = (long) (-m * Math.log(new Random().nextDouble())); long fromNow = (long) (-m * Math.log(Math.random()));
long triggerAt = elapsedRealtime() + fromNow; long triggerAt = elapsedRealtime() + fromNow;
Intent i = new Intent(this, ContactInviteInputActivity.class); Intent i = new Intent(this, ContactLinkExchangeActivity.class);
i.setAction("addContact"); i.setAction("addContact");
i.setFlags(FLAG_ACTIVITY_NEW_TASK); i.setFlags(FLAG_ACTIVITY_NEW_TASK);
i.putExtra("name", name); i.putExtra("name", name);
i.putExtra("timestamp", timestamp); i.putExtra("timestamp", timestamp);
PendingIntent pendingIntent = PendingIntent PendingIntent pendingIntent =
.getActivity(this, (int) timestamp / 1000, i, 0); PendingIntent.getActivity(this, (int) timestamp / 1000, i, 0);
alarmManager.set(ELAPSED_REALTIME, triggerAt, pendingIntent); alarmManager.set(ELAPSED_REALTIME, triggerAt, pendingIntent);
Log.e("TEST", "Setting Alarm in " + MILLISECONDS.toSeconds(fromNow) +
" seconds");
Log.e("TEST", "with contact: " + name);
} }
private void removeFakeRequest(String name, long timestamp) { private void removeFakeRequest(String name, long timestamp) {
if (lifecycleManager.getLifecycleState() != RUNNING) { if (lifecycleManager.getLifecycleState() != RUNNING) {
Log.e("TEST", "Lifecycle not started, not adding contact " + name); LOG.info("Lifecycle not started, not adding contact " + name);
return; return;
} }
Log.e("TEST", "Adding Contact " + name); LOG.info("Adding Contact " + name);
try { try {
messagingManager.removePendingContact(name, timestamp); messagingManager.removePendingContact(name, timestamp);
} catch (DbException e) { } catch (DbException e) {
e.printStackTrace(); logException(LOG, WARNING, e);
} }
} }
} }

View File

@@ -1,10 +1,11 @@
package org.briarproject.briar.android.contact; package org.briarproject.briar.android.contact;
import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AlertDialog; import android.support.annotation.NonNull;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -12,90 +13,43 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.fragment.BaseFragment;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN;
import static android.content.Context.CLIPBOARD_SERVICE; import static android.content.Context.CLIPBOARD_SERVICE;
import static android.content.Intent.ACTION_SEND;
import static android.content.Intent.EXTRA_TEXT;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.support.v4.graphics.drawable.DrawableCompat.setTint; import static android.support.v4.graphics.drawable.DrawableCompat.setTint;
import static android.support.v4.graphics.drawable.DrawableCompat.wrap; import static android.support.v4.graphics.drawable.DrawableCompat.wrap;
import static android.widget.Toast.LENGTH_SHORT;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
import static org.briarproject.bramble.util.StringUtils.getRandomBase32String;
import static org.briarproject.briar.android.util.UiUtils.resolveColorAttribute; import static org.briarproject.briar.android.util.UiUtils.resolveColorAttribute;
@NotNullByDefault public class ContactLinkExchangeFragment extends BaseFragment
public class ContactLinkInputFragment extends BaseFragment
implements TextWatcher { implements TextWatcher {
private ClipboardManager clipboard; static final String TAG = ContactLinkExchangeFragment.class.getName();
private EditText linkInput;
private Button pasteButton;
private EditText contactNameInput;
private Button addButton;
static BaseFragment newInstance(@Nullable String link) { static BaseFragment newInstance(@Nullable String link) {
BaseFragment f = new ContactLinkInputFragment(); BaseFragment f = new ContactLinkExchangeFragment();
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString("link", link); bundle.putString("link", link);
f.setArguments(bundle); f.setArguments(bundle);
return f; return f;
} }
@Nullable private ClipboardManager clipboard;
@Override private EditText linkInput;
public View onCreateView(LayoutInflater inflater, private EditText contactNameInput;
@Nullable ViewGroup container, private Button addButton;
@Nullable Bundle savedInstanceState) {
getActivity().setTitle(R.string.open_link_title);
View v = inflater.inflate(R.layout.fragment_contact_link_input,
container, false);
clipboard = (ClipboardManager) requireNonNull(
getContext().getSystemService(CLIPBOARD_SERVICE));
int color = resolveColorAttribute(getContext(), R.attr.colorControlNormal);
linkInput = v.findViewById(R.id.linkInput);
linkInput.addTextChangedListener(this);
if (SDK_INT < 23) {
Drawable drawable = wrap(linkInput.getCompoundDrawables()[0]);
setTint(drawable, color);
linkInput.setCompoundDrawables(drawable, null, null, null);
}
pasteButton = v.findViewById(R.id.pasteButton);
pasteButton.setOnClickListener(view -> linkInput
.setText(clipboard.getPrimaryClip().getItemAt(0).getText()));
contactNameInput = v.findViewById(R.id.contactNameInput);
contactNameInput.addTextChangedListener(this);
if (SDK_INT < 23) {
Drawable drawable =
wrap(contactNameInput.getCompoundDrawables()[0]);
setTint(drawable, color);
contactNameInput.setCompoundDrawables(drawable, null, null, null);
}
addButton = v.findViewById(R.id.addButton);
addButton.setOnClickListener(view -> onAddButtonClicked());
Button scanCodeButton = v.findViewById(R.id.scanCodeButton);
scanCodeButton.setOnClickListener(view ->
((ContactInviteInputActivity) getActivity()).showCode());
linkInput.setText(getArguments().getString("link"));
return v;
}
public static final String TAG = ContactLinkInputFragment.class.getName();
@Override @Override
public String getUniqueTag() { public String getUniqueTag() {
@@ -107,18 +61,94 @@ public class ContactLinkInputFragment extends BaseFragment
component.inject(this); component.inject(this);
} }
@Nullable
@Override @Override
public void onResume() { public View onCreateView(@NonNull LayoutInflater inflater,
super.onResume(); @Nullable ViewGroup container,
if (hasLinkInClipboard()) pasteButton.setEnabled(true); @Nullable Bundle savedInstanceState) {
else pasteButton.setEnabled(false); if (getActivity() == null || getContext() == null) return null;
getActivity().setTitle(R.string.add_contact_title);
View v = inflater.inflate(R.layout.fragment_contact_link_exchange,
container, false);
clipboard = (ClipboardManager) requireNonNull(
getContext().getSystemService(CLIPBOARD_SERVICE));
int color =
resolveColorAttribute(getContext(), R.attr.colorControlNormal);
contactNameInput = v.findViewById(R.id.contactNameInput);
contactNameInput.addTextChangedListener(this);
if (SDK_INT < 23) {
Drawable drawable =
wrap(contactNameInput.getCompoundDrawables()[0]);
setTint(drawable, color);
contactNameInput.setCompoundDrawables(drawable, null, null, null);
}
linkInput = v.findViewById(R.id.linkInput);
if (SDK_INT < 23) {
Drawable drawable = wrap(linkInput.getCompoundDrawables()[0]);
setTint(drawable, color);
linkInput.setCompoundDrawables(drawable, null, null, null);
}
linkInput.addTextChangedListener(this);
if (getArguments() != null)
linkInput.setText(getArguments().getString("link"));
Button pasteButton = v.findViewById(R.id.pasteButton);
pasteButton.setOnClickListener(view -> {
ClipData clip = clipboard.getPrimaryClip();
if (clip != null)
linkInput.setText(clip.getItemAt(0).getText());
});
Button scanCodeButton = v.findViewById(R.id.scanCodeButton);
scanCodeButton.setOnClickListener(view -> {
ContactLinkExchangeActivity activity = getCastActivity();
if (activity != null) activity.scanCode();
});
String link = "briar://" + getRandomBase32String(64);
TextView linkView = v.findViewById(R.id.linkView);
linkView.setText(link);
ClipData clip = ClipData.newPlainText(
getString(R.string.link_clip_label), link);
Button copyButton = v.findViewById(R.id.copyButton);
copyButton.setOnClickListener(view -> {
clipboard.setPrimaryClip(clip);
Toast.makeText(getContext(), R.string.link_copied_toast,
LENGTH_SHORT).show();
});
Button shareButton = v.findViewById(R.id.shareButton);
shareButton.setOnClickListener(view -> {
Intent i = new Intent(ACTION_SEND);
i.putExtra(EXTRA_TEXT, link);
i.setType("text/plain");
startActivity(i);
});
Button showCodeButton = v.findViewById(R.id.showCodeButton);
showCodeButton.setOnClickListener(
view -> {
ContactLinkExchangeActivity activity = getCastActivity();
if (activity != null) activity.showCode();
});
addButton = v.findViewById(R.id.addButton);
addButton.setOnClickListener(view -> onAddButtonClicked());
return v;
} }
private boolean hasLinkInClipboard() { private ContactLinkExchangeActivity getCastActivity() {
return clipboard.hasPrimaryClip() && return (ContactLinkExchangeActivity) getActivity();
clipboard.getPrimaryClip().getDescription()
.hasMimeType(MIMETYPE_TEXT_PLAIN) &&
clipboard.getPrimaryClip().getItemCount() > 0;
} }
@Override @Override
@@ -129,50 +159,31 @@ public class ContactLinkInputFragment extends BaseFragment
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, public void onTextChanged(CharSequence s, int start, int before,
int count) { int count) {
if (isBriarLink(linkInput.getText()) && getActivity() != null) { updateAddButtonState();
updateAddButtonState();
// linkInput.setText(null);
// ((ContactInviteInputActivity) getActivity()).showAlias();
}
} }
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
} }
private boolean isBriarLink(CharSequence s) { private void updateAddButtonState() {
return getActivity() != null && addButton.setEnabled(contactNameInput.getText().length() > 0 &&
((ContactInviteInputActivity) getActivity()).isBriarLink(s); isBriarLink(linkInput.getText().toString()));
} }
private void updateAddButtonState() { private boolean isBriarLink(CharSequence s) {
addButton.setEnabled(isBriarLink(linkInput.getText()) && ContactLinkExchangeActivity activity = getCastActivity();
contactNameInput.getText().length() > 0); return activity != null && activity.isBriarLink(s);
} }
private void onAddButtonClicked() { private void onAddButtonClicked() {
if (getActivity() == null || getContext() == null) return; ContactLinkExchangeActivity activity = getCastActivity();
if (activity == null) return;
((ContactInviteInputActivity) getActivity()) activity.addFakeRequest(contactNameInput.getText().toString());
.addFakeRequest(contactNameInput.getText().toString());
AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), Intent intent = new Intent(activity, PendingRequestsActivity.class);
R.style.BriarDialogTheme_Neutral); startActivity(intent);
builder.setTitle("Contact requested"); finish();
builder.setMessage(getString(R.string.add_contact_link_question));
builder.setPositiveButton(R.string.yes, (dialog, which) -> {
Intent intent = new Intent(getContext(), PendingRequestsActivity.class);
// intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
});
builder.setNegativeButton(R.string.no, (dialog, which) -> {
startActivity(
new Intent(getContext(),
ContactInviteOutputActivity.class));
finish();
});
builder.show();
} }
} }

View File

@@ -1,86 +0,0 @@
package org.briarproject.briar.android.contact;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import javax.annotation.Nullable;
import static android.content.Context.CLIPBOARD_SERVICE;
import static android.content.Intent.ACTION_SEND;
import static android.content.Intent.EXTRA_TEXT;
import static android.widget.Toast.LENGTH_SHORT;
import static org.briarproject.bramble.util.StringUtils.getRandomBase32String;
@NotNullByDefault
public class ContactLinkOutputFragment extends BaseFragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
getActivity().setTitle(R.string.send_link_title);
View v = inflater.inflate(R.layout.fragment_contact_link_output,
container, false);
String link = "briar://" + getRandomBase32String(64);
TextView linkView = v.findViewById(R.id.linkView);
linkView.setText(link);
ClipboardManager clipboard = (ClipboardManager)
getContext().getSystemService(CLIPBOARD_SERVICE);
if (clipboard == null) throw new AssertionError();
ClipData clip = ClipData.newPlainText(
getString(R.string.link_clip_label), link);
Button copyButton = v.findViewById(R.id.copyButton);
copyButton.setOnClickListener(view -> {
clipboard.setPrimaryClip(clip);
Toast.makeText(getContext(), R.string.link_copied_toast,
LENGTH_SHORT).show();
});
Button shareButton = v.findViewById(R.id.shareButton);
shareButton.setOnClickListener(view -> {
Intent i = new Intent(ACTION_SEND);
i.putExtra(EXTRA_TEXT, link);
i.setType("text/plain");
startActivity(i);
});
Button showCodeButton = v.findViewById(R.id.showCodeButton);
showCodeButton.setOnClickListener(
view -> ((ContactInviteOutputActivity) getActivity()).showCode());
return v;
}
public static final String TAG = ContactLinkOutputFragment.class.getName();
@Override
public String getUniqueTag() {
return TAG;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
}

View File

@@ -10,9 +10,6 @@ import android.support.v4.content.ContextCompat;
import android.support.v4.util.Pair; import android.support.v4.util.Pair;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
@@ -178,41 +175,17 @@ public class ContactListFragment extends BaseFragment implements EventListener,
} }
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onMenuItemClick(FloatingActionButton fab, @Nullable TextView v,
// inflater.inflate(R.menu.contact_list_actions, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_add_contact:
Intent intent =
new Intent(getContext(), ContactExchangeActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onMenuItemClick(FloatingActionButton fab, TextView v,
int itemId) { int itemId) {
switch (itemId) { switch (itemId) {
case R.id.action_add_contact: case R.id.action_add_contact_nearby:
Intent intent = Intent intent =
new Intent(getContext(), ContactExchangeActivity.class); new Intent(getContext(), ContactExchangeActivity.class);
startActivity(intent); startActivity(intent);
return; return;
case R.id.action_open_link: case R.id.action_add_contact_remotely:
startActivity(new Intent(getContext(), startActivity(new Intent(getContext(),
ContactInviteInputActivity.class)); ContactLinkExchangeActivity.class));
return;
case R.id.action_send_link:
startActivity(new Intent(getContext(),
ContactInviteOutputActivity.class));
return; return;
default: default:
return; return;

View File

@@ -5,7 +5,6 @@ import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -13,7 +12,6 @@ import android.widget.Toast;
import com.google.zxing.Result; import com.google.zxing.Result;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.fragment.BaseFragment;
@@ -22,6 +20,8 @@ import org.briarproject.briar.android.keyagreement.CameraView;
import org.briarproject.briar.android.keyagreement.QrCodeDecoder; import org.briarproject.briar.android.keyagreement.QrCodeDecoder;
import org.briarproject.briar.android.util.UiUtils; import org.briarproject.briar.android.util.UiUtils;
import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static android.Manifest.permission.CAMERA; import static android.Manifest.permission.CAMERA;
@@ -29,16 +29,32 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.widget.Toast.LENGTH_LONG; import static android.widget.Toast.LENGTH_LONG;
import static android.widget.Toast.LENGTH_SHORT; import static android.widget.Toast.LENGTH_SHORT;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA;
@NotNullByDefault
public class ContactQrCodeInputFragment extends BaseFragment public class ContactQrCodeInputFragment extends BaseFragment
implements QrCodeDecoder.ResultCallback { implements QrCodeDecoder.ResultCallback {
static final String TAG = ContactQrCodeInputFragment.class.getName();
private static final Logger LOG = Logger.getLogger(TAG);
private CameraView cameraView; private CameraView cameraView;
@Override
public String getUniqueTag() {
return TAG;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
@Override @Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) { public void onActivityCreated(@Nullable Bundle savedInstanceState) {
if (getActivity() == null) throw new AssertionError();
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
getActivity().setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR); getActivity().setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR);
cameraView.setPreviewConsumer(new QrCodeDecoder(this)); cameraView.setPreviewConsumer(new QrCodeDecoder(this));
@@ -46,27 +62,21 @@ public class ContactQrCodeInputFragment extends BaseFragment
@Nullable @Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) { @Nullable Bundle savedInstanceState) {
if (getActivity() == null) return null;
getActivity().setTitle("Scan QR Code"); getActivity().setTitle(R.string.scan_qr_code_title);
View v = inflater.inflate(R.layout.fragment_contact_qr_code_input, View v = inflater.inflate(R.layout.fragment_contact_qr_code_input,
container, false); container, false);
cameraView = v.findViewById(R.id.camera_view); cameraView = v.findViewById(R.id.camera_view);
// Button enterLinkButton = v.findViewById(R.id.enterLinkButton);
// enterLinkButton.setOnClickListener(view ->
// ((ContactInviteInputActivity) getActivity()).showLink());
return v; return v;
} }
public static final String TAG = ContactQrCodeInputFragment.class.getName();
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
@@ -81,7 +91,7 @@ public class ContactQrCodeInputFragment extends BaseFragment
try { try {
cameraView.stop(); cameraView.stop();
} catch (CameraException e) { } catch (CameraException e) {
e.printStackTrace(); logException(LOG, WARNING, e);
} }
} }
@@ -89,23 +99,14 @@ public class ContactQrCodeInputFragment extends BaseFragment
try { try {
cameraView.start(); cameraView.start();
} catch (CameraException e) { } catch (CameraException e) {
e.printStackTrace(); logException(LOG, WARNING, e);
Toast.makeText(getContext(), "Camera Error", LENGTH_SHORT) Toast.makeText(getContext(), R.string.camera_error_toast,
.show(); LENGTH_SHORT).show();
} }
} }
@Override
public String getUniqueTag() {
return TAG;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
private boolean checkPermissions() { private boolean checkPermissions() {
if (getContext() == null) return false;
if (ActivityCompat.checkSelfPermission(getContext(), CAMERA) != if (ActivityCompat.checkSelfPermission(getContext(), CAMERA) !=
PERMISSION_GRANTED) { PERMISSION_GRANTED) {
// Should we show an explanation? // Should we show an explanation?
@@ -113,7 +114,8 @@ public class ContactQrCodeInputFragment extends BaseFragment
DialogInterface.OnClickListener continueListener = DialogInterface.OnClickListener continueListener =
(dialog, which) -> requestPermission(); (dialog, which) -> requestPermission();
AlertDialog.Builder AlertDialog.Builder
builder = new AlertDialog.Builder(getContext(), R.style.BriarDialogTheme); builder = new AlertDialog.Builder(getContext(),
R.style.BriarDialogTheme);
builder.setTitle(R.string.permission_camera_title); builder.setTitle(R.string.permission_camera_title);
builder.setMessage(R.string.permission_camera_request_body); builder.setMessage(R.string.permission_camera_request_body);
builder.setNeutralButton(R.string.continue_button, builder.setNeutralButton(R.string.continue_button,
@@ -131,6 +133,7 @@ public class ContactQrCodeInputFragment extends BaseFragment
@Override @Override
public void onRequestPermissionsResult(int requestCode, public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults) { @NonNull String[] permissions, @NonNull int[] grantResults) {
if (getContext() == null) return;
if (requestCode == REQUEST_PERMISSION_CAMERA) { if (requestCode == REQUEST_PERMISSION_CAMERA) {
// If request is cancelled, the result arrays are empty. // If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && if (grantResults.length > 0 &&
@@ -147,13 +150,13 @@ public class ContactQrCodeInputFragment extends BaseFragment
builder.setPositiveButton(R.string.ok, builder.setPositiveButton(R.string.ok,
UiUtils.getGoToSettingsListener(getContext())); UiUtils.getGoToSettingsListener(getContext()));
builder.setNegativeButton(R.string.cancel, builder.setNegativeButton(R.string.cancel,
(dialog, which) -> showLink(null)); (dialog, which) -> cancel());
builder.show(); builder.show();
} else { } else {
Toast.makeText(getContext(), Toast.makeText(getContext(),
R.string.permission_camera_denied_toast, R.string.permission_camera_denied_toast,
LENGTH_LONG).show(); LENGTH_LONG).show();
showLink(null); cancel();
} }
} }
} }
@@ -163,19 +166,20 @@ public class ContactQrCodeInputFragment extends BaseFragment
requestPermissions(new String[] {CAMERA}, REQUEST_PERMISSION_CAMERA); requestPermissions(new String[] {CAMERA}, REQUEST_PERMISSION_CAMERA);
} }
private void showLink(@Nullable String link) { @Nullable
if (getActivity() != null) private ContactLinkExchangeActivity getCastActivity() {
((ContactInviteInputActivity) getActivity()).showLink(link); return (ContactLinkExchangeActivity) getActivity();
}
private void cancel() {
ContactLinkExchangeActivity activity = getCastActivity();
if (activity != null) activity.linkScanned(null);
} }
@Override @Override
public void handleResult(Result result) { public void handleResult(@NonNull Result result) {
Log.e("TEST", result.toString()); LOG.info("Scanned link: " + result.getText());
if (getActivity() != null && ContactLinkExchangeActivity activity = getCastActivity();
((ContactInviteInputActivity) getActivity()) if (activity != null) activity.linkScanned(result.getText());
.isBriarLink(result.getText())) {
showLink(result.getText());
}
} }
} }

View File

@@ -2,13 +2,12 @@ package org.briarproject.briar.android.contact;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.fragment.BaseFragment;
@@ -16,44 +15,12 @@ import org.briarproject.briar.android.view.QrCodeView;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static org.briarproject.bramble.util.StringUtils.getRandomBase32String; import static org.briarproject.bramble.util.StringUtils.getRandomBase32String;
import static org.briarproject.briar.android.keyagreement.QrCodeUtils.createQrCode; import static org.briarproject.briar.android.keyagreement.QrCodeUtils.createQrCode;
@NotNullByDefault public class ContactQrCodeOutputFragment extends BaseFragment {
public class ContactQrCodeOutputFragment extends BaseFragment
implements QrCodeView.FullscreenListener {
private View linkIntro; static final String TAG = ContactQrCodeOutputFragment.class.getName();
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
getActivity().setTitle("Show my QR Code");
View v = inflater.inflate(R.layout.fragment_contact_qr_code_output,
container, false);
linkIntro = v.findViewById(R.id.linkIntro);
String link = "briar://" + getRandomBase32String(64);
DisplayMetrics dm = getResources().getDisplayMetrics();
Bitmap qrCode = createQrCode(dm, link);
QrCodeView qrCodeView = v.findViewById(R.id.qrCodeView);
qrCodeView.setQrCode(qrCode);
qrCodeView.setFullscreenListener(this);
Button showLinkButton = v.findViewById(R.id.showLinkButton);
showLinkButton.setOnClickListener(
view -> ((ContactInviteOutputActivity) getActivity()).showLink());
return v;
}
public static final String TAG = ContactQrCodeOutputFragment.class.getName();
@Override @Override
public String getUniqueTag() { public String getUniqueTag() {
@@ -65,9 +32,24 @@ public class ContactQrCodeOutputFragment extends BaseFragment
component.inject(this); component.inject(this);
} }
@Nullable
@Override @Override
public void setFullscreen(boolean fullscreen) { public View onCreateView(@NonNull LayoutInflater inflater,
linkIntro.setVisibility(fullscreen ? GONE : VISIBLE); @Nullable ViewGroup container,
} @Nullable Bundle savedInstanceState) {
if (getActivity() == null) return null;
getActivity().setTitle(R.string.show_qr_code_title);
View v = inflater.inflate(R.layout.fragment_contact_qr_code_output,
container, false);
String link = "briar://" + getRandomBase32String(64);
DisplayMetrics dm = getResources().getDisplayMetrics();
Bitmap qrCode = createQrCode(dm, link);
QrCodeView qrCodeView = v.findViewById(R.id.qrCodeView);
qrCodeView.setQrCode(qrCode);
return v;
}
} }

View File

@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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:padding="@dimen/margin_large">
<EditText
android:id="@+id/contactNameInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_person"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_person"
android:drawableTint="?attr/colorControlNormal"
android:hint="@string/contact_name_hint"
android:importantForAutofill="no"
android:inputType="text|textCapWords"
app:layout_constraintBottom_toTopOf="@id/linkInput"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"/>
<EditText
android:id="@+id/linkInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_xlarge"
android:drawableLeft="@drawable/ic_link"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_link"
android:drawableTint="?attr/colorControlNormal"
android:hint="@string/contact_link_hint"
android:importantForAutofill="no"
android:inputType="textUri"
app:layout_constraintBottom_toTopOf="@id/pasteButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/contactNameInput"/>
<Button
android:id="@+id/pasteButton"
style="@style/BriarButtonFlat.Positive.Tiny"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_content_paste"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_content_paste"
android:text="@string/paste_button"
app:layout_constraintBottom_toTopOf="@id/linkIntro"
app:layout_constraintEnd_toStartOf="@id/scanCodeButton"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/linkInput"/>
<Button
android:id="@+id/scanCodeButton"
style="@style/BriarButtonFlat.Positive.Tiny"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_qr_code"
android:drawablePadding="8dp"
android:text="@string/scan_qr_code_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@id/pasteButton"
app:layout_constraintTop_toBottomOf="@id/linkInput"
android:drawableStart="@drawable/ic_qr_code"/>
<TextView
android:id="@+id/linkIntro"
android:gravity="center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_xlarge"
android:text="@string/send_link_instructions"
android:textIsSelectable="true"
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@id/linkView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/pasteButton"/>
<TextView
android:id="@+id/linkView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_medium"
android:background="@color/briar_white"
android:padding="8dp"
android:textColor="@color/briar_primary"
android:textIsSelectable="true"
android:textSize="18sp"
android:typeface="monospace"
app:layout_constraintBottom_toTopOf="@id/copyButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/linkIntro"
tools:text="briar://scnsdflamslkfjgluoblmksdfbwevlewajfdlkjewwhqliafskfjhskdjhvoieiv"/>
<Button
android:id="@+id/copyButton"
style="@style/BriarButtonFlat.Positive.Tiny"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_content_copy"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_content_copy"
android:text="@string/copy_button"
app:layout_constraintBottom_toTopOf="@id/addButton"
app:layout_constraintEnd_toStartOf="@id/shareButton"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/linkView"/>
<Button
android:id="@+id/shareButton"
style="@style/BriarButtonFlat.Positive.Tiny"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/social_share_blue"
android:drawablePadding="8dp"
android:drawableStart="@drawable/social_share_blue"
android:text="@string/share_button"
app:layout_constraintBottom_toBottomOf="@id/copyButton"
app:layout_constraintEnd_toStartOf="@id/showCodeButton"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@id/copyButton"
app:layout_constraintTop_toTopOf="@id/copyButton"/>
<Button
android:id="@+id/showCodeButton"
style="@style/BriarButtonFlat.Positive.Tiny"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_qr_code"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_qr_code"
android:drawableTint="@color/briar_button_text_positive"
android:text="@string/show_qr_code_button"
app:layout_constraintBottom_toBottomOf="@id/copyButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@id/shareButton"
app:layout_constraintTop_toTopOf="@id/copyButton"/>
<Button
android:id="@+id/addButton"
style="@style/BriarButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_xlarge"
android:enabled="false"
android:text="@string/add_contact_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.75"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/copyButton"
tools:enabled="true"/>
</android.support.constraint.ConstraintLayout>

View File

@@ -1,78 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" 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_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView
android:id="@+id/linkIntro"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_large"
android:text="@string/send_code_instructions"
android:textIsSelectable="true"
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@+id/qrCodeView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
android:visibility="gone"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintVertical_weight="1"
tools:visibility="gone"/>
<org.briarproject.briar.android.view.QrCodeView <org.briarproject.briar.android.view.QrCodeView
android:id="@+id/qrCodeView" android:id="@+id/qrCodeView"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent"
android:background="@android:color/white" android:background="@android:color/white"/>
android:textIsSelectable="true"
android:textSize="18sp"
android:typeface="monospace"
app:layout_constraintBottom_toTopOf="@+id/textView2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linkIntro"
app:layout_constraintVertical_weight="1"/>
<TextView </FrameLayout>
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="or"
android:visibility="gone"
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@+id/showLinkButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/qrCodeView"/>
<Button
android:id="@+id/showLinkButton"
style="@style/BriarButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:drawableLeft="@drawable/ic_link"
android:drawablePadding="8dp"
android:visibility="gone"
android:text="Show Link"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2"
app:layout_constraintVertical_bias="1.0"/>
</android.support.constraint.ConstraintLayout>

View File

@@ -4,24 +4,17 @@
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<item <item
android:id="@+id/action_add_contact" android:id="@+id/action_add_contact_nearby"
android:icon="@drawable/ic_add_nearby" android:icon="@drawable/ic_add_nearby"
android:orderInCategory="3" android:orderInCategory="3"
android:title="@string/add_contact_nearby_title" android:title="@string/add_contact_nearby_title"
app:showAsAction="never"/> app:showAsAction="never"/>
<item <item
android:id="@+id/action_open_link" android:id="@+id/action_add_contact_remotely"
android:icon="@drawable/ic_link_down" android:icon="@drawable/ic_link"
android:orderInCategory="2" android:orderInCategory="2"
android:title="@string/open_code_title" android:title="@string/add_contact_remotely_title"
app:showAsAction="never"/>
<item
android:id="@+id/action_send_link"
android:icon="@drawable/ic_link_up"
android:orderInCategory="1"
android:title="@string/send_code_title"
app:showAsAction="never"/> app:showAsAction="never"/>
</menu> </menu>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_switch"
android:title="@string/show_link"
app:showAsAction="never"/>
</menu>

View File

@@ -151,28 +151,24 @@
<string name="connection_error_feedback">If this problem persists, please <a href="feedback">send feedback</a> to help us improve the app.</string> <string name="connection_error_feedback">If this problem persists, please <a href="feedback">send feedback</a> to help us improve the app.</string>
<string name="add_contact_nearby_title">Add Contact Nearby</string> <string name="add_contact_nearby_title">Add Contact Nearby</string>
<string name="open_link_title">Open Link</string> <string name="add_contact_remotely_title">Add Contact with Link</string>
<string name="open_code_title">Open Invite</string>
<string name="send_link_title">Send My Link</string>
<string name="send_code_title">Send My Invite</string>
<string name="show_link">Show Link</string>
<string name="show_code">Show QR code</string>
<string name="contact_name_hint">Contact name</string> <string name="contact_name_hint">Contact name</string>
<string name="contact_link_hint">Contact link</string> <string name="contact_link_hint">Contact link</string>
<string name="paste_button">Paste</string> <string name="paste_button">Paste</string>
<string name="add_contact_button">Request Contact</string> <string name="scan_qr_code_button">QR Code</string>
<string name="share_button">Share</string> <string name="add_contact_button">Add Contact</string>
<string name="copy_button">Copy</string> <string name="copy_button">Copy</string>
<string name="send_link_instructions">Send this link to your contact:</string> <string name="share_button">Share</string>
<string name="send_code_instructions">Let your contact scan this QR code:</string> <string name="show_qr_code_button">QR Code</string>
<string name="send_link_instructions">Give this link to your contact:</string>
<string name="link_clip_label">Briar link</string> <string name="link_clip_label">Briar link</string>
<string name="link_copied_toast">Link copied</string> <string name="link_copied_toast">Link copied</string>
<string name="pending_contact_requests_snackbar">"There are pending contact requests"</string> <string name="pending_contact_requests_snackbar">"There are pending contact requests"</string>
<string name="pending_contact_requests">Pending contact requests</string> <string name="pending_contact_requests">Pending contact requests</string>
<string name="add_contact_link_question">Did you send your link already?</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="add_contact_remote_connecting">Connecting…</string> <string name="add_contact_remote_connecting">Connecting…</string>
<string name="scan_qr_code_title">Scan QR Code</string>
<string name="show_qr_code_title">Your QR Code</string>
<string name="camera_error_toast">Camera Error</string>
<!-- Introductions --> <!-- Introductions -->
<string name="introduction_onboarding_title">Introduce your contacts</string> <string name="introduction_onboarding_title">Introduce your contacts</string>