mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 13:19:52 +01:00
Merge branch '292-reuse-contact-selector' into 'master'
Refactor `ContactListAdapter` to be used for Introductions and Forum Sharing This MR introduces an abstract `BaseContactListAdapter` which provides most of the adapter logic. The original `ContactListAdapter` extends it to show date and online status of the contacts. The new `ContactChooserAdapter` which is used for introductions extends the `ContactListAdapter` and adds logic for graying out contacts from different identities than the currently used one. A new `ContactSelectorAdapter` extends the `BaseContactListAdapter` and allows to select multiple contacts. It offers a method to return a collection of all selected `ContactId`s. Closes #292 See merge request !151
This commit is contained in:
9
briar-android/res/drawable/ic_check_white.xml
Normal file
9
briar-android/res/drawable/ic_check_white.xml
Normal 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="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
|
||||||
|
</vector>
|
||||||
@@ -64,6 +64,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@android:color/tertiary_text_light"
|
android:textColor="@android:color/tertiary_text_light"
|
||||||
android:textSize="@dimen/text_size_tiny"
|
android:textSize="@dimen/text_size_tiny"
|
||||||
|
android:visibility="gone"
|
||||||
tools:text="My Identity"/>
|
tools:text="My Identity"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
61
briar-android/res/layout/list_item_selectable_contact.xml
Normal file
61
briar-android/res/layout/list_item_selectable_contact.xml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
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="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="@dimen/listitem_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/listitem_horizontal_margin"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
>
|
||||||
|
|
||||||
|
<de.hdodenhof.circleimageview.CircleImageView
|
||||||
|
android:id="@+id/avatarView"
|
||||||
|
android:layout_width="@dimen/listitem_picture_size"
|
||||||
|
android:layout_height="@dimen/listitem_picture_size"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginLeft="@dimen/listitem_horizontal_margin"
|
||||||
|
android:layout_marginStart="@dimen/listitem_horizontal_margin"
|
||||||
|
android:transitionName="avatar"
|
||||||
|
app:civ_border_color="@color/briar_text_primary"
|
||||||
|
app:civ_border_width="@dimen/avatar_border_width"
|
||||||
|
tools:src="@drawable/ic_launcher"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/nameView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginLeft="@dimen/listitem_horizontal_margin"
|
||||||
|
android:layout_marginStart="@dimen/listitem_horizontal_margin"
|
||||||
|
android:layout_toEndOf="@+id/avatarView"
|
||||||
|
android:layout_toLeftOf="@+id/checkBox"
|
||||||
|
android:layout_toRightOf="@+id/avatarView"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textColor="@android:color/primary_text_light"
|
||||||
|
android:textSize="@dimen/text_size_large"
|
||||||
|
tools:text="This is a name of a contact"/>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/checkBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
||||||
|
android:clickable="false"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<View style="@style/Divider.ContactList"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
12
briar-android/res/menu/forum_share_actions.xml
Normal file
12
briar-android/res/menu/forum_share_actions.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?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_share_forum"
|
||||||
|
android:icon="@drawable/ic_check_white"
|
||||||
|
android:title="@string/forum_share_with_some"
|
||||||
|
app:showAsAction="always"/>
|
||||||
|
|
||||||
|
</menu>
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
package org.briarproject.android.contact;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.v7.util.SortedList;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.briarproject.R;
|
||||||
|
import org.briarproject.api.contact.ContactId;
|
||||||
|
import org.briarproject.api.identity.Author;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import im.delight.android.identicons.IdenticonDrawable;
|
||||||
|
|
||||||
|
import static android.support.v7.util.SortedList.INVALID_POSITION;
|
||||||
|
|
||||||
|
public abstract class BaseContactListAdapter<VH extends BaseContactListAdapter.BaseContactHolder>
|
||||||
|
extends RecyclerView.Adapter<VH> {
|
||||||
|
|
||||||
|
protected SortedList<ContactListItem> contacts;
|
||||||
|
protected final OnItemClickListener listener;
|
||||||
|
protected Context ctx;
|
||||||
|
|
||||||
|
public BaseContactListAdapter(Context context, OnItemClickListener listener) {
|
||||||
|
this.ctx = context;
|
||||||
|
this.listener = listener;
|
||||||
|
this.contacts = new SortedList<ContactListItem>(ContactListItem.class,
|
||||||
|
new SortedListCallBacks());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(final VH ui, final int position) {
|
||||||
|
final ContactListItem item = getItem(position);
|
||||||
|
|
||||||
|
Author author = item.getContact().getAuthor();
|
||||||
|
ui.avatar.setImageDrawable(
|
||||||
|
new IdenticonDrawable(author.getId().getBytes()));
|
||||||
|
String contactName = author.getName();
|
||||||
|
ui.name.setText(contactName);
|
||||||
|
|
||||||
|
ui.layout.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (listener != null) listener.onItemClick(ui.avatar, item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return contacts.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContactListItem getItem(int position) {
|
||||||
|
if (position == INVALID_POSITION || contacts.size() <= position) {
|
||||||
|
return null; // Not found
|
||||||
|
}
|
||||||
|
return contacts.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateItem(int position, ContactListItem item) {
|
||||||
|
contacts.updateItemAt(position, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int findItemPosition(ContactListItem c) {
|
||||||
|
return contacts.indexOf(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int findItemPosition(ContactId c) {
|
||||||
|
int count = getItemCount();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
ContactListItem item = getItem(i);
|
||||||
|
if (item.getContact().getId().equals(c)) return i;
|
||||||
|
}
|
||||||
|
return INVALID_POSITION; // Not found
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAll(List<ContactListItem> contacts) {
|
||||||
|
this.contacts.addAll(contacts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(ContactListItem contact) {
|
||||||
|
contacts.add(contact);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(ContactListItem contact) {
|
||||||
|
contacts.remove(contact);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
contacts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BaseContactHolder extends RecyclerView.ViewHolder {
|
||||||
|
public final ViewGroup layout;
|
||||||
|
public final ImageView avatar;
|
||||||
|
public final TextView name;
|
||||||
|
|
||||||
|
public BaseContactHolder(View v) {
|
||||||
|
super(v);
|
||||||
|
|
||||||
|
layout = (ViewGroup) v;
|
||||||
|
avatar = (ImageView) v.findViewById(R.id.avatarView);
|
||||||
|
name = (TextView) v.findViewById(R.id.nameView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compareContactListItems(ContactListItem c1, ContactListItem c2) {
|
||||||
|
return compareByName(c1, c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int compareByName(ContactListItem c1, ContactListItem c2) {
|
||||||
|
int authorCompare = c1.getLocalAuthor().getName()
|
||||||
|
.compareTo(c2.getLocalAuthor().getName());
|
||||||
|
if (authorCompare == 0) {
|
||||||
|
// if names are equal, compare by time instead
|
||||||
|
return compareByTime(c1, c2);
|
||||||
|
} else {
|
||||||
|
return authorCompare;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int compareByTime(ContactListItem c1, ContactListItem c2) {
|
||||||
|
long time1 = c1.getTimestamp();
|
||||||
|
long time2 = c2.getTimestamp();
|
||||||
|
if (time1 < time2) return 1;
|
||||||
|
if (time1 > time2) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class SortedListCallBacks extends SortedList.Callback<ContactListItem> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInserted(int position, int count) {
|
||||||
|
notifyItemRangeInserted(position, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChanged(int position, int count) {
|
||||||
|
notifyItemRangeChanged(position, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMoved(int fromPosition, int toPosition) {
|
||||||
|
notifyItemMoved(fromPosition, toPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRemoved(int position, int count) {
|
||||||
|
notifyItemRangeRemoved(position, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(ContactListItem c1, ContactListItem c2) {
|
||||||
|
return compareContactListItems(c1, c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areItemsTheSame(ContactListItem c1, ContactListItem c2) {
|
||||||
|
return c1.getContact().getId().equals(c2.getContact().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areContentsTheSame(ContactListItem c1,
|
||||||
|
ContactListItem c2) {
|
||||||
|
// check for all properties that influence visual
|
||||||
|
// representation of contact
|
||||||
|
if (c1.isConnected() != c2.isConnected()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c1.getUnreadCount() != c2.getUnreadCount()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c1.getTimestamp() != c2.getTimestamp()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnItemClickListener {
|
||||||
|
void onItemClick(View view, ContactListItem item);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,14 +1,7 @@
|
|||||||
package org.briarproject.android.contact;
|
package org.briarproject.android.contact;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.ColorFilter;
|
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.graphics.PorterDuffColorFilter;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.support.v7.util.SortedList;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -17,98 +10,12 @@ import android.widget.ImageView;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.briarproject.R;
|
import org.briarproject.R;
|
||||||
import org.briarproject.api.contact.ContactId;
|
|
||||||
import org.briarproject.api.identity.Author;
|
|
||||||
import org.briarproject.api.identity.AuthorId;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import im.delight.android.identicons.IdenticonDrawable;
|
|
||||||
|
|
||||||
import static android.support.v7.util.SortedList.INVALID_POSITION;
|
|
||||||
|
|
||||||
public class ContactListAdapter
|
public class ContactListAdapter
|
||||||
extends RecyclerView.Adapter<ContactListAdapter.ContactHolder> {
|
extends BaseContactListAdapter<ContactListAdapter.ContactHolder> {
|
||||||
|
|
||||||
private final SortedList<ContactListItem> contacts =
|
public ContactListAdapter(Context context, OnItemClickListener listener) {
|
||||||
new SortedList<ContactListItem>(ContactListItem.class,
|
super(context, listener);
|
||||||
new SortedList.Callback<ContactListItem>() {
|
|
||||||
@Override
|
|
||||||
public void onInserted(int position, int count) {
|
|
||||||
notifyItemRangeInserted(position, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onChanged(int position, int count) {
|
|
||||||
notifyItemRangeChanged(position, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMoved(int fromPosition, int toPosition) {
|
|
||||||
notifyItemMoved(fromPosition, toPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRemoved(int position, int count) {
|
|
||||||
notifyItemRangeRemoved(position, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(ContactListItem c1,
|
|
||||||
ContactListItem c2) {
|
|
||||||
int authorCompare = 0;
|
|
||||||
if (chooser) {
|
|
||||||
authorCompare = c1.getLocalAuthor().getName()
|
|
||||||
.compareTo(
|
|
||||||
c2.getLocalAuthor().getName());
|
|
||||||
}
|
|
||||||
if (authorCompare == 0) {
|
|
||||||
// sort items by time
|
|
||||||
// and do not take unread messages into account
|
|
||||||
long time1 = c1.getTimestamp();
|
|
||||||
long time2 = c2.getTimestamp();
|
|
||||||
if (time1 < time2) return 1;
|
|
||||||
if (time1 > time2) return -1;
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return authorCompare;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean areItemsTheSame(ContactListItem c1,
|
|
||||||
ContactListItem c2) {
|
|
||||||
return c1.getContact().getId()
|
|
||||||
.equals(c2.getContact().getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean areContentsTheSame(ContactListItem c1,
|
|
||||||
ContactListItem c2) {
|
|
||||||
// check for all properties that influence visual
|
|
||||||
// representation of contact
|
|
||||||
if (c1.isConnected() != c2.isConnected()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (c1.getUnreadCount() != c2.getUnreadCount()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (c1.getTimestamp() != c2.getTimestamp()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
private final OnItemClickListener listener;
|
|
||||||
private final boolean chooser;
|
|
||||||
private Context ctx;
|
|
||||||
private AuthorId localAuthorId;
|
|
||||||
|
|
||||||
public ContactListAdapter(Context context, OnItemClickListener listener,
|
|
||||||
boolean chooser) {
|
|
||||||
ctx = context;
|
|
||||||
this.listener = listener;
|
|
||||||
this.chooser = chooser;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -121,38 +28,25 @@ public class ContactListAdapter
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(final ContactHolder ui, final int position) {
|
public void onBindViewHolder(final ContactHolder ui, final int position) {
|
||||||
|
super.onBindViewHolder(ui, position);
|
||||||
|
|
||||||
final ContactListItem item = getItem(position);
|
final ContactListItem item = getItem(position);
|
||||||
|
|
||||||
|
// name and unread count
|
||||||
|
String contactName = item.getContact().getAuthor().getName();
|
||||||
int unread = item.getUnreadCount();
|
int unread = item.getUnreadCount();
|
||||||
if (!chooser && unread > 0) {
|
if (unread > 0) {
|
||||||
ui.layout.setBackgroundColor(
|
|
||||||
ContextCompat.getColor(ctx, R.color.unread_background));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.isConnected()) {
|
|
||||||
ui.bulb.setImageResource(R.drawable.contact_connected);
|
|
||||||
} else {
|
|
||||||
ui.bulb.setImageResource(R.drawable.contact_disconnected);
|
|
||||||
}
|
|
||||||
|
|
||||||
Author author = item.getContact().getAuthor();
|
|
||||||
ui.avatar.setImageDrawable(
|
|
||||||
new IdenticonDrawable(author.getId().getBytes()));
|
|
||||||
String contactName = author.getName();
|
|
||||||
|
|
||||||
if (!chooser && unread > 0) {
|
|
||||||
// TODO show these in a bubble on top of the avatar
|
// TODO show these in a bubble on top of the avatar
|
||||||
ui.name.setText(contactName + " (" + unread + ")");
|
ui.name.setText(contactName + " (" + unread + ")");
|
||||||
|
|
||||||
|
// different background for contacts with unread messages
|
||||||
|
ui.layout.setBackgroundColor(
|
||||||
|
ContextCompat.getColor(ctx, R.color.unread_background));
|
||||||
} else {
|
} else {
|
||||||
ui.name.setText(contactName);
|
ui.name.setText(contactName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chooser) {
|
// date of last message
|
||||||
ui.identity.setText(item.getLocalAuthor().getName());
|
|
||||||
} else {
|
|
||||||
ui.identity.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.isEmpty()) {
|
if (item.isEmpty()) {
|
||||||
ui.date.setText(R.string.no_private_messages);
|
ui.date.setText(R.string.no_private_messages);
|
||||||
} else {
|
} else {
|
||||||
@@ -162,115 +56,33 @@ public class ContactListAdapter
|
|||||||
DateUtils.getRelativeTimeSpanString(ctx, timestamp));
|
DateUtils.getRelativeTimeSpanString(ctx, timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chooser && !item.getLocalAuthor().getId().equals(localAuthorId)) {
|
// online/offline
|
||||||
grayOutItem(ui);
|
if (item.isConnected()) {
|
||||||
}
|
ui.bulb.setImageResource(R.drawable.contact_connected);
|
||||||
|
|
||||||
ui.layout.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
listener.onItemClick(ui.avatar, item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return contacts.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the identity from whose perspective the contact shall be chosen.
|
|
||||||
* This is only used if chooser is true.
|
|
||||||
* @param authorId The ID of the local Author
|
|
||||||
*/
|
|
||||||
public void setLocalAuthor(AuthorId authorId) {
|
|
||||||
localAuthorId = authorId;
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void grayOutItem(final ContactHolder ui) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
|
||||||
float alpha = 0.25f;
|
|
||||||
ui.bulb.setAlpha(alpha);
|
|
||||||
ui.avatar.setAlpha(alpha);
|
|
||||||
ui.name.setAlpha(alpha);
|
|
||||||
ui.date.setAlpha(alpha);
|
|
||||||
ui.identity.setAlpha(alpha);
|
|
||||||
} else {
|
} else {
|
||||||
ColorFilter colorFilter = new PorterDuffColorFilter(Color.GRAY,
|
ui.bulb.setImageResource(R.drawable.contact_disconnected);
|
||||||
PorterDuff.Mode.MULTIPLY);
|
|
||||||
ui.bulb.setColorFilter(colorFilter);
|
|
||||||
ui.avatar.setColorFilter(colorFilter);
|
|
||||||
ui.name.setEnabled(false);
|
|
||||||
ui.date.setEnabled(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContactListItem getItem(int position) {
|
protected static class ContactHolder
|
||||||
if (position == INVALID_POSITION || contacts.size() <= position) {
|
extends BaseContactListAdapter.BaseContactHolder {
|
||||||
return null; // Not found
|
|
||||||
}
|
|
||||||
return contacts.get(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateItem(int position, ContactListItem item) {
|
public final ImageView bulb;
|
||||||
contacts.updateItemAt(position, item);
|
public final TextView date;
|
||||||
}
|
public final TextView identity;
|
||||||
|
|
||||||
public int findItemPosition(ContactId c) {
|
|
||||||
int count = getItemCount();
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
ContactListItem item = getItem(i);
|
|
||||||
if (item.getContact().getId().equals(c)) return i;
|
|
||||||
}
|
|
||||||
return INVALID_POSITION; // Not found
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAll(List<ContactListItem> contacts) {
|
|
||||||
this.contacts.addAll(contacts);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(ContactListItem contact) {
|
|
||||||
contacts.add(contact);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove(ContactListItem contact) {
|
|
||||||
contacts.remove(contact);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
contacts.beginBatchedUpdates();
|
|
||||||
|
|
||||||
while(contacts.size() != 0) {
|
|
||||||
contacts.removeItemAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
contacts.endBatchedUpdates();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ContactHolder extends RecyclerView.ViewHolder {
|
|
||||||
public ViewGroup layout;
|
|
||||||
public ImageView bulb;
|
|
||||||
public ImageView avatar;
|
|
||||||
public TextView name;
|
|
||||||
public TextView identity;
|
|
||||||
public TextView date;
|
|
||||||
|
|
||||||
public ContactHolder(View v) {
|
public ContactHolder(View v) {
|
||||||
super(v);
|
super(v);
|
||||||
|
|
||||||
layout = (ViewGroup) v;
|
|
||||||
bulb = (ImageView) v.findViewById(R.id.bulbView);
|
bulb = (ImageView) v.findViewById(R.id.bulbView);
|
||||||
avatar = (ImageView) v.findViewById(R.id.avatarView);
|
|
||||||
name = (TextView) v.findViewById(R.id.nameView);
|
|
||||||
identity = (TextView) v.findViewById(R.id.identityView);
|
|
||||||
date = (TextView) v.findViewById(R.id.dateView);
|
date = (TextView) v.findViewById(R.id.dateView);
|
||||||
|
identity = (TextView) v.findViewById(R.id.identityView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnItemClickListener {
|
@Override
|
||||||
void onItemClick(View view, ContactListItem item);
|
public int compareContactListItems(ContactListItem c1, ContactListItem c2) {
|
||||||
|
return compareByTime(c1, c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class ContactListFragment extends BaseEventFragment {
|
|||||||
inflater.inflate(R.layout.activity_contact_list, container,
|
inflater.inflate(R.layout.activity_contact_list, container,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
ContactListAdapter.OnItemClickListener onItemClickListener =
|
BaseContactListAdapter.OnItemClickListener onItemClickListener =
|
||||||
new ContactListAdapter.OnItemClickListener() {
|
new ContactListAdapter.OnItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(View view, ContactListItem item) {
|
public void onItemClick(View view, ContactListItem item) {
|
||||||
@@ -124,8 +124,7 @@ public class ContactListFragment extends BaseEventFragment {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
adapter = new ContactListAdapter(getContext(), onItemClickListener,
|
adapter = new ContactListAdapter(getContext(), onItemClickListener);
|
||||||
false);
|
|
||||||
list = (BriarRecyclerView) contentView.findViewById(R.id.contactList);
|
list = (BriarRecyclerView) contentView.findViewById(R.id.contactList);
|
||||||
list.setLayoutManager(new LinearLayoutManager(getContext()));
|
list.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
list.setAdapter(adapter);
|
list.setAdapter(adapter);
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
package org.briarproject.android.contact;
|
|
||||||
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.DialogInterface.OnMultiChoiceClickListener;
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
|
|
||||||
import org.briarproject.R;
|
|
||||||
import org.briarproject.api.contact.Contact;
|
|
||||||
import org.briarproject.api.contact.ContactId;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class SelectContactsDialog implements OnMultiChoiceClickListener {
|
|
||||||
|
|
||||||
private Listener listener = null;
|
|
||||||
private List<Contact> contacts = null;
|
|
||||||
private Set<ContactId> selected = null;
|
|
||||||
|
|
||||||
public void setListener(Listener listener) {
|
|
||||||
this.listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContacts(Collection<Contact> contacts) {
|
|
||||||
this.contacts = new ArrayList<Contact>(contacts);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSelected(Collection<ContactId> selected) {
|
|
||||||
this.selected = new HashSet<ContactId>(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dialog build(Context ctx) {
|
|
||||||
if (listener == null || contacts == null || selected == null)
|
|
||||||
throw new IllegalStateException();
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(ctx,
|
|
||||||
R.style.BriarDialogTheme);
|
|
||||||
int size = contacts.size();
|
|
||||||
String[] names = new String[size];
|
|
||||||
boolean[] checked = new boolean[size];
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
Contact c = contacts.get(i);
|
|
||||||
names[i] = c.getAuthor().getName();
|
|
||||||
checked[i] = selected.contains(c.getId());
|
|
||||||
}
|
|
||||||
builder.setMultiChoiceItems(names, checked, this);
|
|
||||||
builder.setPositiveButton(R.string.done_button,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
listener.contactsSelected(selected);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(R.string.cancel_button,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
listener.contactSelectionCancelled();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return builder.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
|
|
||||||
if (isChecked) selected.add(contacts.get(which).getId());
|
|
||||||
else selected.remove(contacts.get(which).getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Listener {
|
|
||||||
|
|
||||||
void contactsSelected(Collection<ContactId> selected);
|
|
||||||
|
|
||||||
void contactSelectionCancelled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package org.briarproject.android.forum;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
|
||||||
|
import org.briarproject.R;
|
||||||
|
import org.briarproject.android.contact.BaseContactListAdapter;
|
||||||
|
import org.briarproject.android.contact.ContactListItem;
|
||||||
|
import org.briarproject.api.contact.ContactId;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class ContactSelectorAdapter
|
||||||
|
extends
|
||||||
|
BaseContactListAdapter<ContactSelectorAdapter.SelectableContactHolder> {
|
||||||
|
|
||||||
|
public ContactSelectorAdapter(Context context,
|
||||||
|
OnItemClickListener listener) {
|
||||||
|
|
||||||
|
super(context, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SelectableContactHolder onCreateViewHolder(ViewGroup viewGroup,
|
||||||
|
int i) {
|
||||||
|
View v = LayoutInflater.from(ctx)
|
||||||
|
.inflate(R.layout.list_item_selectable_contact, viewGroup,
|
||||||
|
false);
|
||||||
|
|
||||||
|
return new SelectableContactHolder(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(final SelectableContactHolder ui,
|
||||||
|
final int position) {
|
||||||
|
super.onBindViewHolder(ui, position);
|
||||||
|
|
||||||
|
final SelectableContactListItem item =
|
||||||
|
(SelectableContactListItem) getItem(position);
|
||||||
|
|
||||||
|
if (item.isSelected()) {
|
||||||
|
ui.checkBox.setChecked(true);
|
||||||
|
} else {
|
||||||
|
ui.checkBox.setChecked(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ContactId> getSelectedContactIds() {
|
||||||
|
Collection<ContactId> selected = new ArrayList<ContactId>();
|
||||||
|
|
||||||
|
for (int i = 0; i < contacts.size(); i++) {
|
||||||
|
SelectableContactListItem item =
|
||||||
|
(SelectableContactListItem) contacts.get(i);
|
||||||
|
if (item.isSelected()) selected.add(item.getContact().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class SelectableContactHolder
|
||||||
|
extends BaseContactListAdapter.BaseContactHolder {
|
||||||
|
|
||||||
|
private final CheckBox checkBox;
|
||||||
|
|
||||||
|
public SelectableContactHolder(View v) {
|
||||||
|
super(v);
|
||||||
|
|
||||||
|
checkBox = (CheckBox) v.findViewById(R.id.checkBox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareContactListItems(ContactListItem c1, ContactListItem c2) {
|
||||||
|
return compareByName(c1, c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package org.briarproject.android.forum;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
|
import android.support.v4.app.ActivityOptionsCompat;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@@ -42,6 +44,8 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
|
||||||
import static android.view.Gravity.CENTER;
|
import static android.view.Gravity.CENTER;
|
||||||
import static android.view.Gravity.CENTER_HORIZONTAL;
|
import static android.view.Gravity.CENTER_HORIZONTAL;
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
@@ -152,9 +156,13 @@ public class ForumActivity extends BriarActivity implements EventListener,
|
|||||||
return true;
|
return true;
|
||||||
case R.id.action_forum_share:
|
case R.id.action_forum_share:
|
||||||
Intent i2 = new Intent(this, ShareForumActivity.class);
|
Intent i2 = new Intent(this, ShareForumActivity.class);
|
||||||
|
i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
i2.putExtra(GROUP_ID, groupId.getBytes());
|
i2.putExtra(GROUP_ID, groupId.getBytes());
|
||||||
i2.putExtra(FORUM_NAME, forum.getName());
|
i2.putExtra(FORUM_NAME, forum.getName());
|
||||||
startActivity(i2);
|
ActivityOptionsCompat options = ActivityOptionsCompat
|
||||||
|
.makeCustomAnimation(this, android.R.anim.slide_in_left,
|
||||||
|
android.R.anim.slide_out_right);
|
||||||
|
ActivityCompat.startActivity(this, i2, options.toBundle());
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
package org.briarproject.android.forum;
|
|
||||||
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
|
|
||||||
import org.briarproject.R;
|
|
||||||
|
|
||||||
public class NoContactsDialog {
|
|
||||||
|
|
||||||
private Listener listener = null;
|
|
||||||
|
|
||||||
public void setListener(Listener listener) {
|
|
||||||
this.listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dialog build(Context ctx) {
|
|
||||||
if (listener == null) throw new IllegalStateException();
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(ctx,
|
|
||||||
R.style.BriarDialogTheme);
|
|
||||||
builder.setMessage(R.string.no_contacts_prompt);
|
|
||||||
builder.setPositiveButton(R.string.add_button,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
listener.contactCreationSelected();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(R.string.cancel_button,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
listener.contactCreationCancelled();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return builder.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Listener {
|
|
||||||
|
|
||||||
void contactCreationSelected();
|
|
||||||
|
|
||||||
void contactCreationCancelled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package org.briarproject.android.forum;
|
||||||
|
|
||||||
|
import org.briarproject.android.contact.ContactListItem;
|
||||||
|
import org.briarproject.android.contact.ConversationItem;
|
||||||
|
import org.briarproject.api.contact.Contact;
|
||||||
|
import org.briarproject.api.identity.LocalAuthor;
|
||||||
|
import org.briarproject.api.sync.GroupId;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
// This class is not thread-safe
|
||||||
|
public class SelectableContactListItem extends ContactListItem {
|
||||||
|
|
||||||
|
private boolean selected;
|
||||||
|
|
||||||
|
public SelectableContactListItem(Contact contact, LocalAuthor localAuthor,
|
||||||
|
GroupId groupId, boolean selected) {
|
||||||
|
|
||||||
|
super(contact, localAuthor, false, groupId, Collections.<ConversationItem>emptyList());
|
||||||
|
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelected(boolean selected) {
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSelected() {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleSelected() {
|
||||||
|
selected = !selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,67 +2,59 @@ package org.briarproject.android.forum;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.widget.RadioButton;
|
|
||||||
import android.widget.RadioGroup;
|
|
||||||
|
|
||||||
import org.briarproject.R;
|
import org.briarproject.R;
|
||||||
import org.briarproject.android.AndroidComponent;
|
import org.briarproject.android.AndroidComponent;
|
||||||
import org.briarproject.android.BriarActivity;
|
import org.briarproject.android.BriarActivity;
|
||||||
import org.briarproject.android.contact.SelectContactsDialog;
|
import org.briarproject.android.contact.BaseContactListAdapter;
|
||||||
import org.briarproject.android.invitation.AddContactActivity;
|
import org.briarproject.android.contact.ContactListItem;
|
||||||
import org.briarproject.android.util.LayoutUtils;
|
import org.briarproject.android.util.BriarRecyclerView;
|
||||||
import org.briarproject.api.contact.Contact;
|
import org.briarproject.api.contact.Contact;
|
||||||
import org.briarproject.api.contact.ContactId;
|
import org.briarproject.api.contact.ContactId;
|
||||||
import org.briarproject.api.contact.ContactManager;
|
import org.briarproject.api.contact.ContactManager;
|
||||||
import org.briarproject.api.db.DbException;
|
import org.briarproject.api.db.DbException;
|
||||||
import org.briarproject.api.forum.ForumSharingManager;
|
import org.briarproject.api.forum.ForumSharingManager;
|
||||||
|
import org.briarproject.api.identity.IdentityManager;
|
||||||
|
import org.briarproject.api.identity.LocalAuthor;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static android.view.Gravity.CENTER_HORIZONTAL;
|
|
||||||
import static android.view.View.GONE;
|
|
||||||
import static android.view.View.VISIBLE;
|
|
||||||
import static android.widget.LinearLayout.VERTICAL;
|
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.android.forum.ForumActivity.FORUM_NAME;
|
import static org.briarproject.android.forum.ForumActivity.FORUM_NAME;
|
||||||
import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
|
|
||||||
import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP;
|
|
||||||
|
|
||||||
public class ShareForumActivity extends BriarActivity
|
public class ShareForumActivity extends BriarActivity implements
|
||||||
implements OnClickListener, NoContactsDialog.Listener,
|
BaseContactListAdapter.OnItemClickListener {
|
||||||
SelectContactsDialog.Listener {
|
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(ShareForumActivity.class.getName());
|
Logger.getLogger(ShareForumActivity.class.getName());
|
||||||
|
|
||||||
private RadioGroup radioGroup = null;
|
private ContactSelectorAdapter adapter;
|
||||||
private RadioButton shareWithAll = null, shareWithSome = null;
|
|
||||||
private Button shareButton = null;
|
|
||||||
private ProgressBar progress = null;
|
|
||||||
private boolean changed = false;
|
|
||||||
|
|
||||||
// Fields that are accessed from background threads must be volatile
|
// Fields that are accessed from background threads must be volatile
|
||||||
|
@Inject protected volatile IdentityManager identityManager;
|
||||||
@Inject protected volatile ContactManager contactManager;
|
@Inject protected volatile ContactManager contactManager;
|
||||||
@Inject protected volatile ForumSharingManager forumSharingManager;
|
@Inject protected volatile ForumSharingManager forumSharingManager;
|
||||||
private volatile GroupId groupId = null;
|
private volatile GroupId groupId;
|
||||||
private volatile Collection<Contact> contacts = null;
|
|
||||||
private volatile Collection<ContactId> selected = null;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle state) {
|
public void onCreate(Bundle state) {
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
|
|
||||||
|
setContentView(R.layout.introduction_contact_chooser);
|
||||||
|
|
||||||
Intent i = getIntent();
|
Intent i = getIntent();
|
||||||
byte[] b = i.getByteArrayExtra(GROUP_ID);
|
byte[] b = i.getByteArrayExtra(GROUP_ID);
|
||||||
if (b == null) throw new IllegalStateException();
|
if (b == null) throw new IllegalStateException();
|
||||||
@@ -71,44 +63,43 @@ SelectContactsDialog.Listener {
|
|||||||
if (forumName == null) throw new IllegalStateException();
|
if (forumName == null) throw new IllegalStateException();
|
||||||
setTitle(forumName);
|
setTitle(forumName);
|
||||||
|
|
||||||
LinearLayout layout = new LinearLayout(this);
|
adapter = new ContactSelectorAdapter(this, this);
|
||||||
layout.setLayoutParams(MATCH_MATCH);
|
BriarRecyclerView list =
|
||||||
layout.setOrientation(VERTICAL);
|
(BriarRecyclerView) findViewById(R.id.contactList);
|
||||||
layout.setGravity(CENTER_HORIZONTAL);
|
list.setLayoutManager(new LinearLayoutManager(this));
|
||||||
int pad = LayoutUtils.getPadding(this);
|
list.setAdapter(adapter);
|
||||||
layout.setPadding(pad, pad, pad, pad);
|
list.setEmptyText(getString(R.string.no_contacts));
|
||||||
|
}
|
||||||
|
|
||||||
radioGroup = new RadioGroup(this);
|
@Override
|
||||||
radioGroup.setOrientation(VERTICAL);
|
public void onResume() {
|
||||||
radioGroup.setPadding(0, 0, 0, pad);
|
super.onResume();
|
||||||
|
|
||||||
shareWithAll = new RadioButton(this);
|
loadContactsAndVisibility();
|
||||||
shareWithAll.setId(2);
|
}
|
||||||
shareWithAll.setText(R.string.forum_share_with_all);
|
|
||||||
shareWithAll.setOnClickListener(this);
|
|
||||||
radioGroup.addView(shareWithAll);
|
|
||||||
|
|
||||||
shareWithSome = new RadioButton(this);
|
@Override
|
||||||
shareWithSome.setId(3);
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
shareWithSome.setText(R.string.forum_share_with_some);
|
// Inflate the menu items for use in the action bar
|
||||||
shareWithSome.setOnClickListener(this);
|
MenuInflater inflater = getMenuInflater();
|
||||||
radioGroup.addView(shareWithSome);
|
inflater.inflate(R.menu.forum_share_actions, menu);
|
||||||
|
|
||||||
layout.addView(radioGroup);
|
return super.onCreateOptionsMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
shareButton = new Button(this);
|
@Override
|
||||||
shareButton.setLayoutParams(WRAP_WRAP);
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
shareButton.setText(R.string.forum_share_button);
|
// Handle presses on the action bar items
|
||||||
shareButton.setOnClickListener(this);
|
switch (item.getItemId()) {
|
||||||
layout.addView(shareButton);
|
case android.R.id.home:
|
||||||
|
onBackPressed();
|
||||||
progress = new ProgressBar(this);
|
return true;
|
||||||
progress.setLayoutParams(WRAP_WRAP);
|
case R.id.action_share_forum:
|
||||||
progress.setIndeterminate(true);
|
storeVisibility();
|
||||||
progress.setVisibility(GONE);
|
return true;
|
||||||
layout.addView(progress);
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
setContentView(layout);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -116,41 +107,29 @@ SelectContactsDialog.Listener {
|
|||||||
component.inject(this);
|
component.inject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClick(View view) {
|
private void loadContactsAndVisibility() {
|
||||||
if (view == shareWithAll) {
|
|
||||||
changed = true;
|
|
||||||
} else if (view == shareWithSome) {
|
|
||||||
changed = true;
|
|
||||||
if (contacts == null) loadVisibility();
|
|
||||||
else displayVisibility();
|
|
||||||
} else if (view == shareButton) {
|
|
||||||
if (changed) {
|
|
||||||
share();
|
|
||||||
} else {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void share() {
|
|
||||||
// Replace the button with a progress bar
|
|
||||||
shareButton.setVisibility(GONE);
|
|
||||||
progress.setVisibility(VISIBLE);
|
|
||||||
// Update the group in a background thread
|
|
||||||
storeVisibility(shareWithAll.isChecked());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadVisibility() {
|
|
||||||
runOnDbThread(new Runnable() {
|
runOnDbThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
contacts = contactManager.getActiveContacts();
|
List<ContactListItem> contacts =
|
||||||
selected = forumSharingManager.getSharedWith(groupId);
|
new ArrayList<ContactListItem>();
|
||||||
|
Collection<ContactId> selectedContacts =
|
||||||
|
new HashSet<ContactId>(
|
||||||
|
forumSharingManager.getSharedWith(groupId));
|
||||||
|
|
||||||
|
for (Contact c : contactManager.getActiveContacts()) {
|
||||||
|
LocalAuthor localAuthor = identityManager
|
||||||
|
.getLocalAuthor(c.getLocalAuthorId());
|
||||||
|
boolean selected = selectedContacts.contains(c.getId());
|
||||||
|
contacts.add(
|
||||||
|
new SelectableContactListItem(c, localAuthor,
|
||||||
|
groupId, selected));
|
||||||
|
}
|
||||||
long duration = System.currentTimeMillis() - now;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Load took " + duration + " ms");
|
LOG.info("Load took " + duration + " ms");
|
||||||
displayVisibility();
|
displayContacts(contacts);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING))
|
if (LOG.isLoggable(WARNING))
|
||||||
LOG.log(WARNING, e.toString(), e);
|
LOG.log(WARNING, e.toString(), e);
|
||||||
@@ -159,32 +138,22 @@ SelectContactsDialog.Listener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayVisibility() {
|
private void displayContacts(final List<ContactListItem> contact) {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (contacts.isEmpty()) {
|
adapter.addAll(contact);
|
||||||
NoContactsDialog builder = new NoContactsDialog();
|
|
||||||
builder.setListener(ShareForumActivity.this);
|
|
||||||
builder.build(ShareForumActivity.this).show();
|
|
||||||
} else {
|
|
||||||
SelectContactsDialog builder = new SelectContactsDialog();
|
|
||||||
builder.setListener(ShareForumActivity.this);
|
|
||||||
builder.setContacts(contacts);
|
|
||||||
builder.setSelected(selected);
|
|
||||||
builder.build(ShareForumActivity.this).show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeVisibility(final boolean all) {
|
private void storeVisibility() {
|
||||||
runOnDbThread(new Runnable() {
|
runOnDbThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
if (all) forumSharingManager.setSharedWithAll(groupId);
|
Collection<ContactId> selected =
|
||||||
else forumSharingManager.setSharedWith(groupId,
|
adapter.getSelectedContactIds();
|
||||||
selected);
|
forumSharingManager.setSharedWith(groupId, selected);
|
||||||
long duration = System.currentTimeMillis() - now;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Update took " + duration + " ms");
|
LOG.info("Update took " + duration + " ms");
|
||||||
@@ -197,20 +166,10 @@ SelectContactsDialog.Listener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void contactCreationSelected() {
|
@Override
|
||||||
startActivity(new Intent(this, AddContactActivity.class));
|
public void onItemClick(View view, ContactListItem item) {
|
||||||
|
((SelectableContactListItem) item).toggleSelected();
|
||||||
|
adapter.notifyItemChanged(adapter.findItemPosition(item), item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void contactCreationCancelled() {
|
|
||||||
radioGroup.clearCheck();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void contactsSelected(Collection<ContactId> selected) {
|
|
||||||
this.selected = Collections.unmodifiableCollection(selected);
|
|
||||||
share();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void contactSelectionCancelled() {
|
|
||||||
radioGroup.clearCheck();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package org.briarproject.android.introduction;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.ColorFilter;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.PorterDuffColorFilter;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.briarproject.android.contact.ContactListAdapter;
|
||||||
|
import org.briarproject.android.contact.ContactListItem;
|
||||||
|
import org.briarproject.api.identity.AuthorId;
|
||||||
|
|
||||||
|
public class ContactChooserAdapter extends ContactListAdapter {
|
||||||
|
|
||||||
|
private AuthorId localAuthorId;
|
||||||
|
|
||||||
|
public ContactChooserAdapter(Context context,
|
||||||
|
OnItemClickListener listener) {
|
||||||
|
|
||||||
|
super(context, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(final ContactHolder ui, final int position) {
|
||||||
|
super.onBindViewHolder(ui, position);
|
||||||
|
|
||||||
|
final ContactListItem item = getItem(position);
|
||||||
|
|
||||||
|
ui.name.setText(item.getContact().getAuthor().getName());
|
||||||
|
|
||||||
|
ui.identity.setText(item.getLocalAuthor().getName());
|
||||||
|
ui.identity.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
if (!item.getLocalAuthor().getId().equals(localAuthorId)) {
|
||||||
|
grayOutItem(ui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareContactListItems(ContactListItem c1, ContactListItem c2) {
|
||||||
|
return compareByName(c1, c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the identity from whose perspective the contact shall be chosen.
|
||||||
|
* Contacts that belong to a different author will be shown grayed out,
|
||||||
|
* but are still clickable.
|
||||||
|
* @param authorId The ID of the local Author
|
||||||
|
*/
|
||||||
|
public void setLocalAuthor(AuthorId authorId) {
|
||||||
|
localAuthorId = authorId;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void grayOutItem(final ContactHolder ui) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||||
|
float alpha = 0.25f;
|
||||||
|
ui.bulb.setAlpha(alpha);
|
||||||
|
ui.avatar.setAlpha(alpha);
|
||||||
|
ui.name.setAlpha(alpha);
|
||||||
|
ui.date.setAlpha(alpha);
|
||||||
|
ui.identity.setAlpha(alpha);
|
||||||
|
} else {
|
||||||
|
ColorFilter colorFilter = new PorterDuffColorFilter(Color.GRAY,
|
||||||
|
PorterDuff.Mode.MULTIPLY);
|
||||||
|
ui.bulb.setColorFilter(colorFilter);
|
||||||
|
ui.avatar.setColorFilter(colorFilter);
|
||||||
|
ui.name.setEnabled(false);
|
||||||
|
ui.date.setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -47,7 +47,7 @@ public class ContactChooserFragment extends BaseFragment {
|
|||||||
public final static String TAG = "ContactChooserFragment";
|
public final static String TAG = "ContactChooserFragment";
|
||||||
private IntroductionActivity introductionActivity;
|
private IntroductionActivity introductionActivity;
|
||||||
private BriarRecyclerView list;
|
private BriarRecyclerView list;
|
||||||
private ContactListAdapter adapter;
|
private ContactChooserAdapter adapter;
|
||||||
private int contactId;
|
private int contactId;
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
@@ -111,8 +111,7 @@ public class ContactChooserFragment extends BaseFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
adapter =
|
adapter = new ContactChooserAdapter(getActivity(), onItemClickListener);
|
||||||
new ContactListAdapter(getActivity(), onItemClickListener, true);
|
|
||||||
|
|
||||||
list = (BriarRecyclerView) contentView.findViewById(R.id.contactList);
|
list = (BriarRecyclerView) contentView.findViewById(R.id.contactList);
|
||||||
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
|
|||||||
Reference in New Issue
Block a user