diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java index 33bace51e..87c6b89b0 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java @@ -85,7 +85,7 @@ public interface ContactManager { * Removes a {@link PendingContact} that is in state * {@link PendingContactState FAILED}. */ - void removePendingContact(PendingContact pendingContact); + void removePendingContact(PendingContact pendingContact) throws DbException; /** * Returns the contact with the given ID. diff --git a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java index 87109efad..deda660f2 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/contact/ContactManagerImpl.java @@ -5,6 +5,7 @@ import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContactId; +import org.briarproject.bramble.api.contact.event.ContactAddedRemotelyEvent; import org.briarproject.bramble.api.contact.event.PendingContactStateChangedEvent; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseComponent; @@ -19,6 +20,7 @@ import org.briarproject.bramble.api.identity.AuthorInfo; import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.system.Scheduler; import org.briarproject.bramble.api.transport.KeyManager; import java.util.ArrayList; @@ -27,12 +29,18 @@ import java.util.List; import java.util.Random; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; import javax.inject.Inject; import static java.lang.System.currentTimeMillis; +import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.logging.Logger.getLogger; +import static org.briarproject.bramble.api.contact.PendingContactState.ADDING_CONTACT; +import static org.briarproject.bramble.api.contact.PendingContactState.CONNECTED; +import static org.briarproject.bramble.api.contact.PendingContactState.FAILED; import static org.briarproject.bramble.api.contact.PendingContactState.WAITING_FOR_CONNECTION; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; @@ -48,10 +56,12 @@ class ContactManagerImpl implements ContactManager { private static final String REMOTE_CONTACT_LINK = "briar://" + getRandomBase32String(LINK_LENGTH); - // TODO remove + // TODO replace with real implementation private final List pendingContacts = new ArrayList<>(); @DatabaseExecutor private final Executor dbExecutor; + @Scheduler + private final ScheduledExecutorService scheduler; private final DatabaseComponent db; private final KeyManager keyManager; @@ -61,11 +71,13 @@ class ContactManagerImpl implements ContactManager { @Inject ContactManagerImpl(DatabaseComponent db, @DatabaseExecutor Executor dbExecutor, KeyManager keyManager, - IdentityManager identityManager) { + IdentityManager identityManager, @Scheduler + ScheduledExecutorService scheduler) { this.db = db; this.dbExecutor = dbExecutor; this.keyManager = keyManager; this.identityManager = identityManager; + this.scheduler = scheduler; hooks = new CopyOnWriteArrayList<>(); } @@ -113,7 +125,7 @@ class ContactManagerImpl implements ContactManager { return REMOTE_CONTACT_LINK; } - // TODO remove + // TODO replace with real implementation @SuppressWarnings("SameParameterValue") private static String getRandomBase32String(int length) { Random random = new Random(); @@ -134,23 +146,78 @@ class ContactManagerImpl implements ContactManager { @Override public void addRemoteContactRequest(String link, String alias) { // TODO replace with real implementation + PendingContactId id = new PendingContactId( + link.substring(0, PendingContactId.LENGTH).getBytes()); + PendingContact pendingContact = + new PendingContact(id, new byte[MAX_PUBLIC_KEY_LENGTH], + alias, WAITING_FOR_CONNECTION, currentTimeMillis()); dbExecutor.execute(() -> { try { - Thread.sleep(2000); + Thread.sleep(1500); } catch (InterruptedException ignored) { } - PendingContactId id = new PendingContactId(link.getBytes()); - PendingContact pendingContact = - new PendingContact(id, new byte[MAX_PUBLIC_KEY_LENGTH], - alias, WAITING_FOR_CONNECTION, currentTimeMillis()); - pendingContacts.add(pendingContact); - Event e = new PendingContactStateChangedEvent(id, - WAITING_FOR_CONNECTION); try { + getLogger("TMP").warning("WAITING_FOR_CONNECTION"); + pendingContacts.add(pendingContact); + Event e = new PendingContactStateChangedEvent(id, + WAITING_FOR_CONNECTION); db.transaction(true, txn -> txn.attach(e)); } catch (DbException ignored) { } }); + + scheduler.schedule(() -> dbExecutor.execute(() -> { + getLogger("TMP").warning("CONNECTED"); + pendingContacts.remove(pendingContact); + PendingContact updated = new PendingContact(id, + pendingContact.getPublicKey(), alias, CONNECTED, + pendingContact.getTimestamp()); + pendingContacts.add(updated); + Event e = new PendingContactStateChangedEvent(id, CONNECTED); + try { + db.transaction(true, txn -> txn.attach(e)); + } catch (DbException ignored) { + } + }), 20, SECONDS); + + scheduler.schedule(() -> dbExecutor.execute(() -> { + getLogger("TMP").warning("ADDING_CONTACT"); + pendingContacts.remove(pendingContact); + PendingContact updated = new PendingContact(id, + pendingContact.getPublicKey(), alias, ADDING_CONTACT, + pendingContact.getTimestamp()); + pendingContacts.add(updated); + Event e = + new PendingContactStateChangedEvent(id, ADDING_CONTACT); + try { + db.transaction(true, txn -> txn.attach(e)); + } catch (DbException ignored) { + } + }), 40, SECONDS); + + scheduler.schedule(() -> dbExecutor.execute(() -> { + pendingContacts.remove(pendingContact); + Event e; + try { + if (true || new Random().nextBoolean()) { + getLogger("TMP").warning("FAILED"); + e = new PendingContactStateChangedEvent(id, FAILED); + PendingContact updated = new PendingContact(id, + pendingContact.getPublicKey(), alias, FAILED, + pendingContact.getTimestamp()); + pendingContacts.add(updated); + } else { + getLogger("TMP").warning("ADDED"); + ContactId cid = new ContactId(Integer.MAX_VALUE); + AuthorId aid = identityManager.getLocalAuthor().getId(); + Contact c = new Contact(cid, null, aid, alias, + new byte[MAX_PUBLIC_KEY_LENGTH], true); + e = new ContactAddedRemotelyEvent(c); + } + db.transaction(true, txn -> txn.attach(e)); + } catch (DbException ignored) { + } + }), 60, SECONDS); } @Override diff --git a/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java index 06d0124b6..a9dee6d24 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/contact/ContactManagerImplTest.java @@ -24,6 +24,7 @@ import org.junit.Test; import java.util.Collection; import java.util.Random; import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -59,8 +60,10 @@ public class ContactManagerImplTest extends BrambleMockTestCase { public ContactManagerImplTest() { Executor dbExecutor = new ImmediateExecutor(); + ScheduledExecutorService scheduler = + context.mock(ScheduledExecutorService.class); contactManager = new ContactManagerImpl(db, dbExecutor, keyManager, - identityManager); + identityManager, scheduler); } @Test diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java index d9af1c9f4..4d80f3215 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/AddContactViewModel.java @@ -13,17 +13,12 @@ import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import java.util.concurrent.Executor; -import java.util.logging.Logger; import javax.inject.Inject; -import static java.util.logging.Logger.getLogger; - @NotNullByDefault public class AddContactViewModel extends AndroidViewModel { - private static Logger LOG = getLogger(AddContactViewModel.class.getName()); - private final ContactManager contactManager; @DatabaseExecutor private final Executor dbExecutor; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingContactListener.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingContactListener.java new file mode 100644 index 000000000..b9090224a --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingContactListener.java @@ -0,0 +1,9 @@ +package org.briarproject.briar.android.contact.add.remote; + +import org.briarproject.bramble.api.contact.PendingContact; + +interface PendingContactListener { + + void onFailedPendingContactRemoved(PendingContact pendingContact); + +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsActivity.java index dbf0d7aba..a11eccde7 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsActivity.java @@ -1,18 +1,13 @@ package org.briarproject.briar.android.contact.add.remote; +import android.arch.lifecycle.ViewModelProvider; +import android.arch.lifecycle.ViewModelProviders; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.widget.LinearLayoutManager; import android.view.MenuItem; -import org.briarproject.bramble.api.contact.Contact; -import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.PendingContact; -import org.briarproject.bramble.api.contact.event.ContactAddedEvent; -import org.briarproject.bramble.api.db.DbException; -import org.briarproject.bramble.api.event.Event; -import org.briarproject.bramble.api.event.EventBus; -import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.briar.R; @@ -28,13 +23,12 @@ import javax.inject.Inject; @MethodsNotNullByDefault @ParametersNotNullByDefault public class PendingRequestsActivity extends BriarActivity - implements EventListener { + implements PendingContactListener { @Inject - ContactManager contactManager; - @Inject - EventBus eventBus; + ViewModelProvider.Factory viewModelFactory; + private PendingRequestsViewModel viewModel; private PendingRequestsAdapter adapter; private BriarRecyclerView list; @@ -54,33 +48,29 @@ public class PendingRequestsActivity extends BriarActivity ab.setDisplayHomeAsUpEnabled(true); } - adapter = new PendingRequestsAdapter(this, PendingContact.class); + viewModel = ViewModelProviders.of(this, viewModelFactory) + .get(PendingRequestsViewModel.class); + viewModel.getPendingContacts() + .observe(this, this::onPendingContactsChanged); + + adapter = new PendingRequestsAdapter(this, this, PendingContact.class); list = findViewById(R.id.list); + list.setEmptyText(R.string.no_pending_contacts); list.setLayoutManager(new LinearLayoutManager(this)); list.setAdapter(adapter); + list.showProgressBar(); } @Override public void onStart() { super.onStart(); - eventBus.addListener(this); list.startPeriodicUpdate(); - runOnDbThread(() -> { - try { - Collection contacts = - contactManager.getPendingContacts(); - addPendingContacts(contacts); - } catch (DbException e) { - e.printStackTrace(); - } - }); } @Override protected void onStop() { super.onStop(); list.stopPeriodicUpdate(); - adapter.clear(); } @Override @@ -95,31 +85,23 @@ public class PendingRequestsActivity extends BriarActivity } @Override - public void eventOccurred(Event e) { - if (e instanceof ContactAddedEvent) { - runOnDbThread(() -> { - try { - Contact contact = contactManager - .getContact(((ContactAddedEvent) e).getContactId()); - runOnUiThreadUnlessDestroyed(() -> { - adapter.remove(contact); - if (adapter.isEmpty()) finish(); - }); - } catch (DbException e1) { - e1.printStackTrace(); - } - }); + public void onFailedPendingContactRemoved(PendingContact pendingContact) { + adapter.remove(pendingContact); + viewModel.removePendingContact(pendingContact); + } + + private void onPendingContactsChanged(Collection contacts) { + if (contacts.isEmpty()) { + if (!adapter.isEmpty()) { + // all previous contacts have been removed, so we can finish + supportFinishAfterTransition(); + } else { + adapter.clear(); + list.showData(); + } + } else { + adapter.setItems(contacts); } } - private void addPendingContacts(Collection contacts) { - runOnUiThreadUnlessDestroyed(() -> { - if (contacts.isEmpty()) { - list.showData(); - } else { - adapter.addAll(contacts); - } - }); - } - } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsAdapter.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsAdapter.java index 53b9bb1e8..89a5d35cb 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsAdapter.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsAdapter.java @@ -5,7 +5,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.briar.R; @@ -15,8 +14,12 @@ import org.briarproject.briar.android.util.BriarAdapter; public class PendingRequestsAdapter extends BriarAdapter { - public PendingRequestsAdapter(Context ctx, Class c) { + private final PendingContactListener listener; + + public PendingRequestsAdapter(Context ctx, PendingContactListener listener, + Class c) { super(ctx, c); + this.listener = listener; } @Override @@ -24,7 +27,7 @@ public class PendingRequestsAdapter extends ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate( R.layout.list_item_pending_contact, viewGroup, false); - return new PendingRequestsViewHolder(v); + return new PendingRequestsViewHolder(v, listener); } @Override @@ -52,14 +55,4 @@ public class PendingRequestsAdapter extends item1.getTimestamp() == item2.getTimestamp(); } - // TODO use PendingContactId - public void remove(Contact contact) { - for (int i = 0; i < items.size(); i++) { - if (items.get(i).getAlias().equals(contact.getAuthor().getName())) { - items.removeItemAt(i); - return; - } - } - } - } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsViewHolder.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsViewHolder.java index 4bacdd533..7fd552f31 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsViewHolder.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsViewHolder.java @@ -3,6 +3,7 @@ package org.briarproject.briar.android.contact.add.remote; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView.ViewHolder; import android.view.View; +import android.widget.Button; import android.widget.TextView; import org.briarproject.bramble.api.contact.PendingContact; @@ -10,33 +11,41 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.briar.R; import org.briarproject.briar.android.view.TextAvatarView; -import static org.briarproject.bramble.util.StringUtils.toUtf8; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; import static org.briarproject.briar.android.util.UiUtils.formatDate; @NotNullByDefault public class PendingRequestsViewHolder extends ViewHolder { + private final PendingContactListener listener; private final TextAvatarView avatar; private final TextView name; private final TextView time; private final TextView status; + private final Button button; - public PendingRequestsViewHolder(View v) { + public PendingRequestsViewHolder(View v, PendingContactListener listener) { super(v); avatar = v.findViewById(R.id.avatar); name = v.findViewById(R.id.name); time = v.findViewById(R.id.time); status = v.findViewById(R.id.status); + button = v.findViewById(R.id.button); + this.listener = listener; } public void bind(PendingContact item) { avatar.setText(item.getAlias()); - avatar.setBackgroundBytes(toUtf8(item.getAlias() + item.getTimestamp())); + avatar.setBackgroundBytes(item.getId().getBytes()); name.setText(item.getAlias()); time.setText(formatDate(time.getContext(), item.getTimestamp())); + button.setOnClickListener( + v -> listener.onFailedPendingContactRemoved(item)); int color = ContextCompat .getColor(status.getContext(), R.color.briar_green); + int buttonVisibility = GONE; switch (item.getState()) { case WAITING_FOR_CONNECTION: color = ContextCompat @@ -50,15 +59,16 @@ public class PendingRequestsViewHolder extends ViewHolder { status.setText(R.string.adding_contact); break; case FAILED: - // TODO add remove button color = ContextCompat .getColor(status.getContext(), R.color.briar_red); status.setText(R.string.adding_contact_failed); + buttonVisibility = VISIBLE; break; default: throw new IllegalStateException(); } status.setTextColor(color); + button.setVisibility(buttonVisibility); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsViewModel.java new file mode 100644 index 000000000..431e8cd99 --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/remote/PendingRequestsViewModel.java @@ -0,0 +1,95 @@ +package org.briarproject.briar.android.contact.add.remote; + +import android.app.Application; +import android.arch.lifecycle.AndroidViewModel; +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.MutableLiveData; + +import org.briarproject.bramble.api.contact.ContactManager; +import org.briarproject.bramble.api.contact.PendingContact; +import org.briarproject.bramble.api.contact.event.ContactAddedRemotelyEvent; +import org.briarproject.bramble.api.contact.event.PendingContactStateChangedEvent; +import org.briarproject.bramble.api.db.DatabaseExecutor; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.event.Event; +import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.event.EventListener; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.util.Collection; +import java.util.concurrent.Executor; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import static java.util.logging.Level.WARNING; +import static java.util.logging.Logger.getLogger; +import static org.briarproject.bramble.util.LogUtils.logException; + +@NotNullByDefault +public class PendingRequestsViewModel extends AndroidViewModel + implements EventListener { + + private final Logger LOG = + getLogger(PendingRequestsViewModel.class.getName()); + + @DatabaseExecutor + private final Executor dbExecutor; + private final ContactManager contactManager; + private final EventBus eventBus; + + private final MutableLiveData> pendingContacts = + new MutableLiveData<>(); + + @Inject + public PendingRequestsViewModel(Application application, + @DatabaseExecutor Executor dbExecutor, + ContactManager contactManager, EventBus eventBus) { + super(application); + this.dbExecutor = dbExecutor; + this.contactManager = contactManager; + this.eventBus = eventBus; + this.eventBus.addListener(this); + loadPendingContacts(); + } + + @Override + protected void onCleared() { + super.onCleared(); + eventBus.removeListener(this); + } + + @Override + public void eventOccurred(Event e) { + if (e instanceof ContactAddedRemotelyEvent || + e instanceof PendingContactStateChangedEvent) { + loadPendingContacts(); + } + } + + private void loadPendingContacts() { + dbExecutor.execute(() -> { + try { + pendingContacts.postValue(contactManager.getPendingContacts()); + } catch (DbException e) { + logException(LOG, WARNING, e); + } + }); + } + + LiveData> getPendingContacts() { + return pendingContacts; + } + + void removePendingContact(PendingContact pendingContact) { + dbExecutor.execute(() -> { + try { + contactManager.removePendingContact(pendingContact); + } catch (DbException e) { + logException(LOG, WARNING, e); + } + }); + loadPendingContacts(); + } + +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/ViewModelModule.java b/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/ViewModelModule.java index 712ec64c2..63e8c9eee 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/ViewModelModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/viewmodel/ViewModelModule.java @@ -4,6 +4,7 @@ import android.arch.lifecycle.ViewModel; import android.arch.lifecycle.ViewModelProvider; import org.briarproject.briar.android.contact.add.remote.AddContactViewModel; +import org.briarproject.briar.android.contact.add.remote.PendingRequestsViewModel; import org.briarproject.briar.android.conversation.ConversationViewModel; import org.briarproject.briar.android.conversation.ImageViewModel; @@ -34,6 +35,12 @@ public abstract class ViewModelModule { abstract ViewModel bindAddContactViewModel( AddContactViewModel addContactViewModel); + @Binds + @IntoMap + @ViewModelKey(PendingRequestsViewModel.class) + abstract ViewModel bindPendingRequestsViewModel( + PendingRequestsViewModel pendingRequestsViewModel); + @Binds @Singleton abstract ViewModelProvider.Factory bindViewModelFactory( diff --git a/briar-android/src/main/res/layout/fragment_link_exchange.xml b/briar-android/src/main/res/layout/fragment_link_exchange.xml index e2bf15d19..339fff186 100644 --- a/briar-android/src/main/res/layout/fragment_link_exchange.xml +++ b/briar-android/src/main/res/layout/fragment_link_exchange.xml @@ -147,6 +147,7 @@ android:text="@string/share_button" app:layout_constraintBottom_toBottomOf="@id/copyButton" app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toEndOf="@id/copyButton" app:layout_constraintTop_toTopOf="@id/copyButton"/> diff --git a/briar-android/src/main/res/layout/list_item_pending_contact.xml b/briar-android/src/main/res/layout/list_item_pending_contact.xml index 02b24c6e5..1420fba72 100644 --- a/briar-android/src/main/res/layout/list_item_pending_contact.xml +++ b/briar-android/src/main/res/layout/list_item_pending_contact.xml @@ -11,11 +11,10 @@ android:id="@+id/avatar" android:layout_width="@dimen/listitem_picture_frame_size" android:layout_height="@dimen/listitem_picture_frame_size" - android:layout_marginBottom="8dp" + android:layout_marginBottom="@dimen/listitem_horizontal_margin" android:layout_marginLeft="@dimen/listitem_horizontal_margin" android:layout_marginStart="@dimen/listitem_horizontal_margin" - android:layout_marginTop="8dp" - app:layout_constraintBottom_toTopOf="@+id/divider" + android:layout_marginTop="@dimen/listitem_horizontal_margin" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> @@ -47,37 +46,49 @@ android:layout_marginEnd="16dp" android:layout_marginRight="16dp" android:layout_marginTop="8dp" - android:text="@string/waiting_for_contact_to_come_online" + android:text="@string/adding_contact_failed" app:layout_constrainedWidth="true" - app:layout_constraintBottom_toTopOf="@+id/divider" app:layout_constraintEnd_toStartOf="@+id/time" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="@+id/name" - app:layout_constraintTop_toBottomOf="@+id/name"/> + app:layout_constraintTop_toBottomOf="@+id/name" + tools:textColor="@color/briar_red"/> +