Add Activities for receiving and entering contact link

This commit is contained in:
Torsten Grote
2018-09-24 18:33:15 -03:00
parent cdf4f3a24b
commit a8080ad84b
13 changed files with 445 additions and 6 deletions

View File

@@ -126,6 +126,9 @@ dependencies {
}
implementation 'com.github.chrisbanes:PhotoView:2.1.4' // later versions already use androidx
// prototype
implementation "com.leinardi.android:speed-dial:2.0.0"
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
annotationProcessor "com.github.bumptech.glide:compiler:$glideVersion"

View File

@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="org.briarproject.briar"
xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
<uses-feature android:name="android.hardware.camera" android:required="false"/>
@@ -29,7 +30,8 @@
android:label="@string/app_name"
android:logo="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/BriarTheme">
android:theme="@style/BriarTheme"
tools:ignore="GoogleAppIndexingWarning">
<receiver
android:name="org.briarproject.briar.android.login.SignInReminderReceiver"
@@ -422,5 +424,19 @@
android:launchMode="singleTask"
android:theme="@style/BriarTheme.NoActionBar"/>
<!-- Prototype -->
<activity
android:name=".android.contact.ContactLinkOutputActivity"
android:theme="@style/BriarTheme"/>
<activity
android:name=".android.contact.ContactLinkInputActivity"
android:theme="@style/BriarTheme"
android:windowSoftInputMode="stateHidden|adjustResize">
<intent-filter>
<data android:scheme="briar"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -15,6 +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.ContactLinkInputActivity;
import org.briarproject.briar.android.contact.ContactLinkOutputActivity;
import org.briarproject.briar.android.contact.ContactListFragment;
import org.briarproject.briar.android.contact.ContactModule;
import org.briarproject.briar.android.conversation.AliasDialogFragment;
@@ -171,6 +173,9 @@ public interface ActivityComponent {
void inject(UnlockActivity activity);
void inject(ContactLinkOutputActivity activity);
void inject(ContactLinkInputActivity activity);
// Fragments
void inject(AuthorNameFragment fragment);

View File

@@ -0,0 +1,128 @@
package org.briarproject.briar.android.contact;
import android.content.ClipboardManager;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import javax.annotation.Nullable;
import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN;
import static android.widget.Toast.LENGTH_SHORT;
import static java.util.Objects.requireNonNull;
public class ContactLinkInputActivity extends BriarActivity
implements TextWatcher {
private ClipboardManager clipboard;
private EditText linkInput;
private Button pasteButton;
private EditText contactNameInput;
private Button addButton;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@Override
public void onCreate(@Nullable Bundle state) {
super.onCreate(state);
setContentView(R.layout.activity_contact_link_input);
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setDisplayHomeAsUpEnabled(true);
}
setTitle("Enter contact link");
clipboard = (ClipboardManager) requireNonNull(
getSystemService(CLIPBOARD_SERVICE));
linkInput = findViewById(R.id.linkInput);
linkInput.addTextChangedListener(this);
pasteButton = findViewById(R.id.pasteButton);
pasteButton.setOnClickListener(v -> {
linkInput
.setText(clipboard.getPrimaryClip().getItemAt(0).getText());
});
contactNameInput = findViewById(R.id.contactNameInput);
contactNameInput.addTextChangedListener(this);
addButton = findViewById(R.id.addButton);
addButton.setOnClickListener(v -> {
Toast.makeText(this,
"Contact " + contactNameInput.getText() + " requested",
LENGTH_SHORT).show();
});
}
@Override
public void onResume() {
super.onResume();
if (hasLinkInClipboard()) pasteButton.setEnabled(true);
else pasteButton.setEnabled(false);
}
private boolean hasLinkInClipboard() {
return clipboard.hasPrimaryClip() &&
clipboard.getPrimaryClip().getDescription()
.hasMimeType(MIMETYPE_TEXT_PLAIN) &&
clipboard.getPrimaryClip().getItemCount() > 0;
}
@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) {
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private boolean isBriarLink(CharSequence s) {
Log.e("TEST", s.toString());
// briar://pfmrkyclibynikzg
Log.e("TEST", "'" + s.subSequence(0, 8).toString() + "'");
Log.e("TEST", "LENGTH?" + (s.length() == 24));
Log.e("TEST", "SUB?" + (s.toString().startsWith("briar://")));
Log.e("TEST", "IS BRIAR LINK?" +
(s.length() == 24 && s.toString().startsWith("briar://")));
return s.length() == 24 && s.toString().startsWith("briar://");
}
private void updateAddButtonState() {
addButton.setEnabled(isBriarLink(linkInput.getText()) &&
contactNameInput.getText().length() > 0);
}
}

View File

@@ -0,0 +1,73 @@
package org.briarproject.briar.android.contact;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import javax.annotation.Nullable;
import static android.widget.Toast.LENGTH_SHORT;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
public class ContactLinkOutputActivity extends BriarActivity {
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@Override
public void onCreate(@Nullable Bundle state) {
super.onCreate(state);
setContentView(R.layout.activity_contact_link_ouput);
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setDisplayHomeAsUpEnabled(true);
}
setTitle(R.string.add_contact_via_link_title);
String link = "briar://" + getRandomString(16);
TextView linkView = findViewById(R.id.linkView);
linkView.setText(link);
ClipboardManager clipboard = (ClipboardManager)
getSystemService(CLIPBOARD_SERVICE);
if (clipboard == null) throw new AssertionError();
ClipData clip = ClipData.newPlainText("Briar link", link);
Button button = findViewById(R.id.button);
button.setOnClickListener(v -> {
clipboard.setPrimaryClip(clip);
Toast.makeText(this, "Link copied!", LENGTH_SHORT).show();
});
Button enterLinkButton = findViewById(R.id.enterLinkButton);
enterLinkButton.setOnClickListener(v -> startActivity(
new Intent(this, ContactLinkInputActivity.class)));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

View File

@@ -2,8 +2,10 @@ package org.briarproject.briar.android.contact;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.util.Pair;
import android.support.v7.widget.LinearLayoutManager;
import android.view.LayoutInflater;
@@ -13,6 +15,9 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.leinardi.android.speeddial.SpeedDialActionItem;
import com.leinardi.android.speeddial.SpeedDialView;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
@@ -49,6 +54,7 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
import static android.os.Build.VERSION.SDK_INT;
import static android.support.design.widget.Snackbar.LENGTH_INDEFINITE;
import static android.support.v4.app.ActivityOptionsCompat.makeSceneTransitionAnimation;
import static android.support.v4.view.ViewCompat.getTransitionName;
import static java.util.logging.Level.WARNING;
@@ -59,7 +65,8 @@ import static org.briarproject.briar.android.conversation.ConversationActivity.C
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ContactListFragment extends BaseFragment implements EventListener {
public class ContactListFragment extends BaseFragment implements EventListener,
SpeedDialView.OnActionSelectedListener {
public static final String TAG = ContactListFragment.class.getName();
private static final Logger LOG = Logger.getLogger(TAG);
@@ -73,6 +80,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
private ContactListAdapter adapter;
private BriarRecyclerView list;
private Snackbar snackbar;
// Fields that are accessed from background threads must be volatile
@Inject
@@ -105,7 +113,11 @@ public class ContactListFragment extends BaseFragment implements EventListener {
getActivity().setTitle(R.string.contact_list_button);
View contentView = inflater.inflate(R.layout.list, container, false);
View contentView = inflater.inflate(R.layout.fragment_contact_list, container, false);
SpeedDialView speedDialView = contentView.findViewById(R.id.speedDial);
speedDialView.inflate(R.menu.contact_list_actions);
speedDialView.setOnActionSelectedListener(this);
OnContactClickListener<ContactListItem> onContactClickListener =
(view, item) -> {
@@ -144,12 +156,21 @@ public class ContactListFragment extends BaseFragment implements EventListener {
list.setEmptyText(getString(R.string.no_contacts));
list.setEmptyAction(getString(R.string.no_contacts_action));
snackbar =
Snackbar.make(contentView, "There are pending contact requests",
LENGTH_INDEFINITE);
snackbar.getView().setBackgroundResource(R.color.briar_primary);
snackbar.setAction(R.string.show, v -> startActivity(
new Intent(getContext(), ContactLinkInputActivity.class)));
snackbar.setActionTextColor(ContextCompat
.getColor(getContext(), R.color.briar_button_text_positive));
return contentView;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.contact_list_actions, menu);
// inflater.inflate(R.menu.contact_list_actions, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@@ -167,6 +188,23 @@ public class ContactListFragment extends BaseFragment implements EventListener {
}
}
@Override
public boolean onActionSelected(SpeedDialActionItem item) {
switch (item.getId()) {
case R.id.action_add_contact:
Intent intent =
new Intent(getContext(), ContactExchangeActivity.class);
startActivity(intent);
return true;
case R.id.action_add_contact_via_link:
startActivity(new Intent(getContext(),
ContactLinkOutputActivity.class));
return true;
default:
return false;
}
}
@Override
public void onStart() {
super.onStart();
@@ -175,6 +213,8 @@ public class ContactListFragment extends BaseFragment implements EventListener {
notificationManager.clearAllIntroductionNotifications();
loadContacts();
list.startPeriodicUpdate();
snackbar.show();
}
@Override

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M3.9,12c0,-1.71 1.39,-3.1 3.1,-3.1h4L11,7L7,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5h4v-1.9L7,15.1c-1.71,0 -3.1,-1.39 -3.1,-3.1zM8,13h8v-2L8,11v2zM17,7h-4v1.9h4c1.71,0 3.1,1.39 3.1,3.1s-1.39,3.1 -3.1,3.1h-4L13,17h4c2.76,0 5,-2.24 5,-5s-2.24,-5 -5,-5z"/>
</vector>

View File

@@ -0,0 +1,67 @@
<?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">
<EditText
android:id="@+id/linkInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:hint="Enter Briar link"
android:inputType="textUri"
app:layout_constraintEnd_toStartOf="@+id/pasteButton"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"/>
<Button
android:id="@+id/pasteButton"
style="@style/BriarButtonFlat.Positive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="Paste"
app:layout_constraintBottom_toBottomOf="@+id/linkInput"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/linkInput"
app:layout_constraintTop_toTopOf="@+id/linkInput"/>
<EditText
android:id="@+id/contactNameInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:hint="Contact Name"
android:inputType="textUri"
app:layout_constraintEnd_toStartOf="@+id/addButton"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linkInput"
app:layout_constraintVertical_chainStyle="packed"/>
<Button
android:id="@+id/addButton"
style="@style/BriarButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:enabled="false"
android:text="Add Contact"
app:layout_constraintBottom_toBottomOf="@+id/contactNameInput"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/contactNameInput"
app:layout_constraintTop_toTopOf="@+id/contactNameInput"
tools:enabled="true"/>
</android.support.constraint.ConstraintLayout>

View File

@@ -0,0 +1,67 @@
<?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">
<TextView
android:id="@+id/linkIntro"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Copy this link and send it to the contact you want to add:"
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_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"/>
<TextView
android:id="@+id/linkView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:textIsSelectable="true"
android:textSize="18sp"
android:typeface="monospace"
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linkIntro"
tools:text="briar://scnsdflamslmksdflksdf"/>
<Button
android:id="@+id/button"
style="@style/BriarButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Copy link"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/enterLinkButton"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linkView"/>
<Button
android:id="@+id/enterLinkButton"
style="@style/BriarButtonFlat.Positive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:text="Enter Link"
app:layout_constraintBottom_toBottomOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/button"
app:layout_constraintTop_toTopOf="@+id/button"/>
</android.support.constraint.ConstraintLayout>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.briarproject.briar.android.view.BriarRecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:scrollToEnd="false"/>
<com.leinardi.android.speeddial.SpeedDialView
android:id="@+id/speedDial"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
app:sdMainFabClosedSrc="@drawable/ic_add_white"/>
</android.support.design.widget.CoordinatorLayout>

View File

@@ -6,7 +6,13 @@
<item
android:id="@+id/action_add_contact"
android:icon="@drawable/ic_add_white"
android:title="@string/add_contact_title"
android:title="@string/add_contact_nearby_title"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_add_contact_via_link"
android:icon="@drawable/ic_link"
android:title="@string/add_contact_via_link_title"
app:showAsAction="never"/>
</menu>

View File

@@ -164,6 +164,9 @@
<string name="connection_error_explanation">Please check that you\'re both connected to the same Wi-Fi network.</string>
<string name="connection_error_feedback">If this problem persists, please <a href="feedback">send feedback</a> to help us improve the app.</string>
<string name="add_contact_nearby_title">Add contact nearby</string>
<string name="add_contact_via_link_title">Add contact via link</string>
<!-- Introductions -->
<string name="introduction_onboarding_title">Introduce your contacts</string>
<string name="introduction_onboarding_text">You can introduce your contacts to each other, so they don\'t need to meet in person to connect on Briar.</string>

View File

@@ -116,6 +116,7 @@ dependencyVerification {
'com.ibm.icu:icu4j:53.1:icu4j-53.1.jar:e37a4467bac5cdeb02c5c4b8e5063d2f4e67b69e3c7df6d6b610f13185572bab',
'com.jraska:falcon:1.0.4:falcon-1.0.4.aar:6114a48d8b3814f75fc69b5e84dc087c1254883874eae8a36bd778979800630a',
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'com.leinardi.android:speed-dial:2.0.0:speed-dial-2.0.0.aar:c219aac9e4e803c85a5ebf47f160b31736bc7b17ca56c024ce6803f11fc18741',
'com.squareup:javawriter:2.1.1:javawriter-2.1.1.jar:f699823d0081f69cbb676c1845ea222e0ada79bc88a53e5d22d8bd02d328f57e',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',