diff --git a/briar-android/src/main/AndroidManifest.xml b/briar-android/src/main/AndroidManifest.xml index 7bc6ba185..fe14a2018 100644 --- a/briar-android/src/main/AndroidManifest.xml +++ b/briar-android/src/main/AndroidManifest.xml @@ -415,14 +415,9 @@ - - diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java index a30b5d086..d87161bbb 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java @@ -15,11 +15,8 @@ import org.briarproject.briar.android.blog.ReblogFragment; import org.briarproject.briar.android.blog.RssFeedImportActivity; import org.briarproject.briar.android.blog.RssFeedManageActivity; import org.briarproject.briar.android.blog.WriteBlogPostActivity; -import org.briarproject.briar.android.contact.ContactAliasInputFragment; -import org.briarproject.briar.android.contact.ContactInviteInputActivity; -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.ContactLinkExchangeActivity; +import org.briarproject.briar.android.contact.ContactLinkExchangeFragment; import org.briarproject.briar.android.contact.ContactListFragment; import org.briarproject.briar.android.contact.ContactModule; import org.briarproject.briar.android.contact.ContactQrCodeInputFragment; @@ -175,14 +172,9 @@ public interface ActivityComponent { void inject(UnlockActivity activity); - void inject(ContactInviteOutputActivity activity); - void inject(ContactInviteInputActivity activity); + void inject(ContactLinkExchangeActivity 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 void inject(AuthorNameFragment fragment); @@ -228,4 +220,11 @@ public interface ActivityComponent { void inject(ScreenFilterDialogFragment fragment); void inject(ContactExchangeErrorFragment fragment); + + void inject(ContactLinkExchangeFragment fragment); + + void inject(ContactQrCodeOutputFragment fragment); + + void inject(ContactQrCodeInputFragment fragment); + } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactAliasInputFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactAliasInputFragment.java deleted file mode 100644 index 5b7698e8c..000000000 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactAliasInputFragment.java +++ /dev/null @@ -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(); - } - - -} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactInviteOutputActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactInviteOutputActivity.java deleted file mode 100644 index fe26df258..000000000 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactInviteOutputActivity.java +++ /dev/null @@ -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()); - } - -} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactInviteInputActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeActivity.java similarity index 77% rename from briar-android/src/main/java/org/briarproject/briar/android/contact/ContactInviteInputActivity.java rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeActivity.java index 2e0a9d7af..b0e42b160 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactInviteInputActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeActivity.java @@ -5,7 +5,6 @@ import android.app.PendingIntent; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.ActionBar; -import android.util.Log; import android.view.MenuItem; 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.api.messaging.MessagingManager; -import java.util.Random; +import java.util.logging.Logger; import javax.annotation.Nullable; 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.os.SystemClock.elapsedRealtime; import static java.util.Objects.requireNonNull; -import static java.util.concurrent.TimeUnit.MILLISECONDS; 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.util.LogUtils.logException; -public class ContactInviteInputActivity extends BriarActivity implements +public class ContactLinkExchangeActivity extends BriarActivity implements BaseFragmentListener { + private static final Logger LOG = + Logger.getLogger(ContactLinkExchangeActivity.class.getName()); + @Inject LifecycleManager lifecycleManager; @Inject @@ -65,13 +68,13 @@ public class ContactInviteInputActivity extends BriarActivity implements String text = i.getStringExtra(EXTRA_TEXT); if (text != null) { showInitialFragment( - ContactLinkInputFragment.newInstance(text)); + ContactLinkExchangeFragment.newInstance(text)); return; } String uri = i.getDataString(); if (uri != null) { showInitialFragment( - ContactLinkInputFragment.newInstance(uri)); + ContactLinkExchangeFragment.newInstance(uri)); return; } } else if ("addContact".equals(action)) { @@ -82,7 +85,7 @@ public class ContactInviteInputActivity extends BriarActivity implements } } 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}$"); } - void showLink(@Nullable String link) { - showInitialFragment(ContactLinkInputFragment.newInstance(link)); - } - - void showCode() { + void scanCode() { showNextFragment(new ContactQrCodeInputFragment()); } - void showAlias() { - showNextFragment(new ContactAliasInputFragment()); + void linkScanned(@Nullable String link) { + showNextFragment(ContactLinkExchangeFragment.newInstance(link)); + } + + void showCode() { + showNextFragment(new ContactQrCodeOutputFragment()); } void addFakeRequest(String name) { @@ -119,40 +122,35 @@ public class ContactInviteInputActivity extends BriarActivity implements try { messagingManager.addNewPendingContact(name, timestamp); } catch (DbException e) { - e.printStackTrace(); + logException(LOG, WARNING, e); } AlarmManager alarmManager = (AlarmManager) requireNonNull(getSystemService(ALARM_SERVICE)); 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; - Intent i = new Intent(this, ContactInviteInputActivity.class); + Intent i = new Intent(this, ContactLinkExchangeActivity.class); i.setAction("addContact"); i.setFlags(FLAG_ACTIVITY_NEW_TASK); i.putExtra("name", name); i.putExtra("timestamp", timestamp); - PendingIntent pendingIntent = PendingIntent - .getActivity(this, (int) timestamp / 1000, i, 0); + PendingIntent pendingIntent = + PendingIntent.getActivity(this, (int) timestamp / 1000, i, 0); 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) { if (lifecycleManager.getLifecycleState() != RUNNING) { - Log.e("TEST", "Lifecycle not started, not adding contact " + name); + LOG.info("Lifecycle not started, not adding contact " + name); return; } - Log.e("TEST", "Adding Contact " + name); + LOG.info("Adding Contact " + name); try { messagingManager.removePendingContact(name, timestamp); } catch (DbException e) { - e.printStackTrace(); + logException(LOG, WARNING, e); } } - } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkInputFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeFragment.java similarity index 50% rename from briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkInputFragment.java rename to briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeFragment.java index 4d58467a9..d7105a936 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkInputFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeFragment.java @@ -1,10 +1,11 @@ package org.briarproject.briar.android.contact; +import android.content.ClipData; import android.content.ClipboardManager; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.support.v7.app.AlertDialog; +import android.support.annotation.NonNull; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; @@ -12,90 +13,43 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; 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.android.activity.ActivityComponent; import org.briarproject.briar.android.fragment.BaseFragment; import javax.annotation.Nullable; -import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN; 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.support.v4.graphics.drawable.DrawableCompat.setTint; import static android.support.v4.graphics.drawable.DrawableCompat.wrap; +import static android.widget.Toast.LENGTH_SHORT; import static java.util.Objects.requireNonNull; +import static org.briarproject.bramble.util.StringUtils.getRandomBase32String; import static org.briarproject.briar.android.util.UiUtils.resolveColorAttribute; -@NotNullByDefault -public class ContactLinkInputFragment extends BaseFragment +public class ContactLinkExchangeFragment extends BaseFragment implements TextWatcher { - private ClipboardManager clipboard; - private EditText linkInput; - private Button pasteButton; - private EditText contactNameInput; - private Button addButton; + static final String TAG = ContactLinkExchangeFragment.class.getName(); static BaseFragment newInstance(@Nullable String link) { - BaseFragment f = new ContactLinkInputFragment(); + BaseFragment f = new ContactLinkExchangeFragment(); Bundle bundle = new Bundle(); bundle.putString("link", link); f.setArguments(bundle); return f; } - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, - @Nullable ViewGroup container, - @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(); + private ClipboardManager clipboard; + private EditText linkInput; + private EditText contactNameInput; + private Button addButton; @Override public String getUniqueTag() { @@ -107,18 +61,94 @@ public class ContactLinkInputFragment extends BaseFragment component.inject(this); } + @Nullable @Override - public void onResume() { - super.onResume(); - if (hasLinkInClipboard()) pasteButton.setEnabled(true); - else pasteButton.setEnabled(false); + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + 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() { - return clipboard.hasPrimaryClip() && - clipboard.getPrimaryClip().getDescription() - .hasMimeType(MIMETYPE_TEXT_PLAIN) && - clipboard.getPrimaryClip().getItemCount() > 0; + private ContactLinkExchangeActivity getCastActivity() { + return (ContactLinkExchangeActivity) getActivity(); } @Override @@ -129,50 +159,31 @@ public class ContactLinkInputFragment extends BaseFragment @Override public void onTextChanged(CharSequence s, int start, int before, int count) { - if (isBriarLink(linkInput.getText()) && getActivity() != null) { - updateAddButtonState(); -// linkInput.setText(null); -// ((ContactInviteInputActivity) getActivity()).showAlias(); - } + 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 && + isBriarLink(linkInput.getText().toString())); } - private void updateAddButtonState() { - addButton.setEnabled(isBriarLink(linkInput.getText()) && - contactNameInput.getText().length() > 0); + private boolean isBriarLink(CharSequence s) { + ContactLinkExchangeActivity activity = getCastActivity(); + return activity != null && activity.isBriarLink(s); } private void onAddButtonClicked() { - if (getActivity() == null || getContext() == null) return; + ContactLinkExchangeActivity activity = getCastActivity(); + if (activity == null) return; - ((ContactInviteInputActivity) getActivity()) - .addFakeRequest(contactNameInput.getText().toString()); + activity.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(), 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(); + Intent intent = new Intent(activity, PendingRequestsActivity.class); + startActivity(intent); + finish(); } - } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkOutputFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkOutputFragment.java deleted file mode 100644 index 531d740ab..000000000 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkOutputFragment.java +++ /dev/null @@ -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); - } - - -} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java index fe6e800dc..dc41f094d 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java @@ -10,9 +10,6 @@ import android.support.v4.content.ContextCompat; import android.support.v4.util.Pair; import android.support.v7.widget.LinearLayoutManager; import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; @@ -178,41 +175,17 @@ public class ContactListFragment extends BaseFragment implements EventListener, } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { -// 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, + public void onMenuItemClick(FloatingActionButton fab, @Nullable TextView v, int itemId) { switch (itemId) { - case R.id.action_add_contact: + case R.id.action_add_contact_nearby: Intent intent = new Intent(getContext(), ContactExchangeActivity.class); startActivity(intent); return; - case R.id.action_open_link: + case R.id.action_add_contact_remotely: startActivity(new Intent(getContext(), - ContactInviteInputActivity.class)); - return; - case R.id.action_send_link: - startActivity(new Intent(getContext(), - ContactInviteOutputActivity.class)); + ContactLinkExchangeActivity.class)); return; default: return; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactQrCodeInputFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactQrCodeInputFragment.java index dd1bfccb6..8dcffe960 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactQrCodeInputFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactQrCodeInputFragment.java @@ -5,7 +5,6 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AlertDialog; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -13,7 +12,6 @@ import android.widget.Toast; import com.google.zxing.Result; -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; @@ -22,6 +20,8 @@ import org.briarproject.briar.android.keyagreement.CameraView; import org.briarproject.briar.android.keyagreement.QrCodeDecoder; import org.briarproject.briar.android.util.UiUtils; +import java.util.logging.Logger; + import javax.annotation.Nullable; 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.widget.Toast.LENGTH_LONG; 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; -@NotNullByDefault public class ContactQrCodeInputFragment extends BaseFragment implements QrCodeDecoder.ResultCallback { + static final String TAG = ContactQrCodeInputFragment.class.getName(); + + private static final Logger LOG = Logger.getLogger(TAG); + private CameraView cameraView; + @Override + public String getUniqueTag() { + return TAG; + } + + @Override + public void injectFragment(ActivityComponent component) { + component.inject(this); + } + @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { + if (getActivity() == null) throw new AssertionError(); super.onActivityCreated(savedInstanceState); getActivity().setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR); cameraView.setPreviewConsumer(new QrCodeDecoder(this)); @@ -46,27 +62,21 @@ public class ContactQrCodeInputFragment extends BaseFragment @Nullable @Override - public View onCreateView(LayoutInflater inflater, + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @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, container, false); cameraView = v.findViewById(R.id.camera_view); - -// Button enterLinkButton = v.findViewById(R.id.enterLinkButton); -// enterLinkButton.setOnClickListener(view -> -// ((ContactInviteInputActivity) getActivity()).showLink()); - return v; } - public static final String TAG = ContactQrCodeInputFragment.class.getName(); - @Override public void onStart() { super.onStart(); @@ -81,7 +91,7 @@ public class ContactQrCodeInputFragment extends BaseFragment try { cameraView.stop(); } catch (CameraException e) { - e.printStackTrace(); + logException(LOG, WARNING, e); } } @@ -89,23 +99,14 @@ public class ContactQrCodeInputFragment extends BaseFragment try { cameraView.start(); } catch (CameraException e) { - e.printStackTrace(); - Toast.makeText(getContext(), "Camera Error", LENGTH_SHORT) - .show(); + logException(LOG, WARNING, e); + Toast.makeText(getContext(), R.string.camera_error_toast, + LENGTH_SHORT).show(); } } - @Override - public String getUniqueTag() { - return TAG; - } - - @Override - public void injectFragment(ActivityComponent component) { - component.inject(this); - } - private boolean checkPermissions() { + if (getContext() == null) return false; if (ActivityCompat.checkSelfPermission(getContext(), CAMERA) != PERMISSION_GRANTED) { // Should we show an explanation? @@ -113,7 +114,8 @@ public class ContactQrCodeInputFragment extends BaseFragment DialogInterface.OnClickListener continueListener = (dialog, which) -> requestPermission(); 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.setMessage(R.string.permission_camera_request_body); builder.setNeutralButton(R.string.continue_button, @@ -131,6 +133,7 @@ public class ContactQrCodeInputFragment extends BaseFragment @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if (getContext() == null) return; if (requestCode == REQUEST_PERMISSION_CAMERA) { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && @@ -147,13 +150,13 @@ public class ContactQrCodeInputFragment extends BaseFragment builder.setPositiveButton(R.string.ok, UiUtils.getGoToSettingsListener(getContext())); builder.setNegativeButton(R.string.cancel, - (dialog, which) -> showLink(null)); + (dialog, which) -> cancel()); builder.show(); } else { Toast.makeText(getContext(), R.string.permission_camera_denied_toast, LENGTH_LONG).show(); - showLink(null); + cancel(); } } } @@ -163,19 +166,20 @@ public class ContactQrCodeInputFragment extends BaseFragment requestPermissions(new String[] {CAMERA}, REQUEST_PERMISSION_CAMERA); } - private void showLink(@Nullable String link) { - if (getActivity() != null) - ((ContactInviteInputActivity) getActivity()).showLink(link); + @Nullable + private ContactLinkExchangeActivity getCastActivity() { + return (ContactLinkExchangeActivity) getActivity(); + } + + private void cancel() { + ContactLinkExchangeActivity activity = getCastActivity(); + if (activity != null) activity.linkScanned(null); } @Override - public void handleResult(Result result) { - Log.e("TEST", result.toString()); - if (getActivity() != null && - ((ContactInviteInputActivity) getActivity()) - .isBriarLink(result.getText())) { - showLink(result.getText()); - } + public void handleResult(@NonNull Result result) { + LOG.info("Scanned link: " + result.getText()); + ContactLinkExchangeActivity activity = getCastActivity(); + if (activity != null) activity.linkScanned(result.getText()); } - } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactQrCodeOutputFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactQrCodeOutputFragment.java index c3d29ee62..51588f5ff 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactQrCodeOutputFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactQrCodeOutputFragment.java @@ -2,13 +2,12 @@ package org.briarproject.briar.android.contact; import android.graphics.Bitmap; import android.os.Bundle; +import android.support.annotation.NonNull; import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; -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; @@ -16,44 +15,12 @@ import org.briarproject.briar.android.view.QrCodeView; 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.briar.android.keyagreement.QrCodeUtils.createQrCode; -@NotNullByDefault -public class ContactQrCodeOutputFragment extends BaseFragment - implements QrCodeView.FullscreenListener { +public class ContactQrCodeOutputFragment extends BaseFragment { - private View linkIntro; - - @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(); + static final String TAG = ContactQrCodeOutputFragment.class.getName(); @Override public String getUniqueTag() { @@ -65,9 +32,24 @@ public class ContactQrCodeOutputFragment extends BaseFragment component.inject(this); } + @Nullable @Override - public void setFullscreen(boolean fullscreen) { - linkIntro.setVisibility(fullscreen ? GONE : VISIBLE); - } + public View onCreateView(@NonNull LayoutInflater inflater, + @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; + } } diff --git a/briar-android/src/main/res/layout/fragment_contact_link_exchange.xml b/briar-android/src/main/res/layout/fragment_contact_link_exchange.xml new file mode 100644 index 000000000..f86dbb524 --- /dev/null +++ b/briar-android/src/main/res/layout/fragment_contact_link_exchange.xml @@ -0,0 +1,164 @@ + + + + + + + +