diff --git a/briar-android/res/layout/activity_available_forums.xml b/briar-android/res/layout/activity_available_forums.xml
new file mode 100644
index 000000000..7177fe175
--- /dev/null
+++ b/briar-android/res/layout/activity_available_forums.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/briar-android/res/layout/list_item_available_forum.xml b/briar-android/res/layout/list_item_available_forum.xml
new file mode 100644
index 000000000..0129b9d6b
--- /dev/null
+++ b/briar-android/res/layout/list_item_available_forum.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index e5d21dec3..e0daa614e 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -102,6 +102,7 @@
Type forum post
Available Forums
Joined Forum
+ Forum Invitation Declined
Shared by %s
You don\'t have any contacts. Add a contact now?
Add
diff --git a/briar-android/src/org/briarproject/android/contact/BaseContactListAdapter.java b/briar-android/src/org/briarproject/android/contact/BaseContactListAdapter.java
index 590c7a2d7..908afe483 100644
--- a/briar-android/src/org/briarproject/android/contact/BaseContactListAdapter.java
+++ b/briar-android/src/org/briarproject/android/contact/BaseContactListAdapter.java
@@ -21,14 +21,14 @@ import static android.support.v7.util.SortedList.INVALID_POSITION;
public abstract class BaseContactListAdapter
extends RecyclerView.Adapter {
- protected SortedList contacts;
+ protected final SortedList 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.class,
+ this.contacts = new SortedList<>(ContactListItem.class,
new SortedListCallBacks());
}
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
index f685e0d06..dd7a722e7 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
@@ -1,34 +1,30 @@
package org.briarproject.android.forum;
import android.os.Bundle;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.ListView;
+import android.support.v7.widget.LinearLayoutManager;
import android.widget.Toast;
import org.briarproject.R;
import org.briarproject.android.AndroidComponent;
import org.briarproject.android.BriarActivity;
-import org.briarproject.android.util.ListLoadingProgressBar;
+import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.NoSuchGroupException;
import org.briarproject.api.event.ContactRemovedEvent;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.event.EventListener;
+import org.briarproject.api.event.ForumInvitationReceivedEvent;
import org.briarproject.api.event.GroupAddedEvent;
import org.briarproject.api.event.GroupRemovedEvent;
-import org.briarproject.api.event.MessageValidatedEvent;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumManager;
import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.sync.ClientId;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import java.util.logging.Logger;
import javax.inject.Inject;
@@ -36,16 +32,15 @@ import javax.inject.Inject;
import static android.widget.Toast.LENGTH_SHORT;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
+import static org.briarproject.android.forum.AvailableForumsAdapter.AvailableForumClickListener;
public class AvailableForumsActivity extends BriarActivity
-implements EventListener, OnItemClickListener {
+ implements EventListener, AvailableForumClickListener {
private static final Logger LOG =
Logger.getLogger(AvailableForumsActivity.class.getName());
- private AvailableForumsAdapter adapter = null;
- private ListView list = null;
+ private AvailableForumsAdapter adapter;
// Fields that are accessed from background threads must be volatile
@Inject protected volatile ForumManager forumManager;
@@ -56,15 +51,13 @@ implements EventListener, OnItemClickListener {
public void onCreate(Bundle state) {
super.onCreate(state);
- adapter = new AvailableForumsAdapter(this);
- list = new ListView(this);
- list.setLayoutParams(MATCH_MATCH);
- list.setAdapter(adapter);
- list.setOnItemClickListener(this);
+ setContentView(R.layout.activity_available_forums);
- // Show a progress bar while the list is loading
- ListLoadingProgressBar loading = new ListLoadingProgressBar(this);
- setContentView(loading);
+ adapter = new AvailableForumsAdapter(this, this);
+ BriarRecyclerView list =
+ (BriarRecyclerView) findViewById(R.id.availableForumsView);
+ list.setLayoutManager(new LinearLayoutManager(this));
+ list.setAdapter(adapter);
}
@Override
@@ -113,11 +106,12 @@ implements EventListener, OnItemClickListener {
LOG.info("No forums available, finishing");
finish();
} else {
- setContentView(list);
adapter.clear();
+ List list =
+ new ArrayList<>(available.size());
for (ForumContacts f : available)
- adapter.add(new AvailableForumsItem(f));
- adapter.sort(AvailableForumsItemComparator.INSTANCE);
+ list.add(new AvailableForumsItem(f));
+ adapter.addAll(list);
}
}
});
@@ -145,37 +139,33 @@ implements EventListener, OnItemClickListener {
LOG.info("Forum removed, reloading");
loadForums();
}
- } else if (e instanceof MessageValidatedEvent) {
- MessageValidatedEvent m = (MessageValidatedEvent) e;
- ClientId c = m.getClientId();
- if (m.isValid() && !m.isLocal()
- && c.equals(forumSharingManager.getClientId())) {
- LOG.info("Available forums updated, reloading");
- loadForums();
- }
+ } else if (e instanceof ForumInvitationReceivedEvent) {
+ LOG.info("Available forums updated, reloading");
+ loadForums();
}
}
- public void onItemClick(AdapterView> parent, View view, int position,
- long id) {
- AvailableForumsItem item = adapter.getItem(position);
- Collection shared = new ArrayList<>();
- for (Contact c : item.getContacts()) shared.add(c.getId());
- subscribe(item.getForum(), shared);
- String joined = getString(R.string.forum_joined_toast);
- Toast.makeText(this, joined, LENGTH_SHORT).show();
+ public void onItemClick(AvailableForumsItem item, boolean accept) {
+ respondToInvitation(item.getForum(), accept);
+
+ // show toast
+ int res = R.string.forum_declined_toast;
+ if (accept) res = R.string.forum_joined_toast;
+ Toast.makeText(this, res, LENGTH_SHORT).show();
}
- private void subscribe(final Forum f, final Collection shared) {
+ private void respondToInvitation(final Forum f, final boolean accept) {
runOnDbThread(new Runnable() {
public void run() {
try {
- forumManager.addForum(f);
+ forumSharingManager.respondToInvitation(f, accept);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
+ loadForums();
}
});
}
+
}
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java
index e5969e3be..0cd0e8181 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsAdapter.java
@@ -1,57 +1,160 @@
package org.briarproject.android.forum;
import android.content.Context;
+import android.support.v7.util.SortedList;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.LinearLayout;
+import android.widget.Button;
import android.widget.TextView;
import org.briarproject.R;
-import org.briarproject.android.util.LayoutUtils;
import org.briarproject.api.contact.Contact;
import org.briarproject.util.StringUtils;
import java.util.ArrayList;
import java.util.Collection;
-import static android.text.TextUtils.TruncateAt.END;
-import static android.widget.LinearLayout.VERTICAL;
+class AvailableForumsAdapter extends
+ RecyclerView.Adapter {
-class AvailableForumsAdapter extends ArrayAdapter {
+ private final Context ctx;
+ private final AvailableForumClickListener listener;
+ private final SortedList forums =
+ new SortedList<>(AvailableForumsItem.class,
+ new SortedListCallBacks());
- private final int pad;
+ AvailableForumsAdapter(Context ctx,
+ AvailableForumClickListener listener) {
- AvailableForumsAdapter(Context ctx) {
- super(ctx, android.R.layout.simple_expandable_list_item_1,
- new ArrayList());
- pad = LayoutUtils.getPadding(ctx);
+ this.ctx = ctx;
+ this.listener = listener;
}
@Override
- public View getView(int position, View convertView, ViewGroup parent) {
- AvailableForumsItem item = getItem(position);
- Context ctx = getContext();
+ public AvailableForumViewHolder onCreateViewHolder(ViewGroup parent,
+ int viewType) {
- LinearLayout layout = new LinearLayout(ctx);
- layout.setOrientation(VERTICAL);
-
- TextView name = new TextView(ctx);
- name.setTextSize(18);
- name.setSingleLine();
- name.setEllipsize(END);
- name.setPadding(pad, pad, pad, pad);
- name.setText(item.getForum().getName());
- layout.addView(name);
-
- TextView status = new TextView(ctx);
- status.setPadding(pad, 0, pad, pad);
- Collection names = new ArrayList();
- for (Contact c : item.getContacts()) names.add(c.getAuthor().getName());
- String format = ctx.getString(R.string.shared_by_format);
- status.setText(String.format(format, StringUtils.join(names, ", ")));
- layout.addView(status);
-
- return layout;
+ View v = LayoutInflater.from(ctx)
+ .inflate(R.layout.list_item_available_forum, parent, false);
+ return new AvailableForumViewHolder(v);
}
+
+ @Override
+ public void onBindViewHolder(AvailableForumViewHolder ui, int position) {
+ final AvailableForumsItem item = getItem(position);
+
+ ui.name.setText(item.getForum().getName());
+
+ Collection names = new ArrayList<>();
+ for (Contact c : item.getContacts()) names.add(c.getAuthor().getName());
+ ui.sharedBy.setText(ctx.getString(R.string.shared_by_format,
+ StringUtils.join(names, ", ")));
+
+ ui.accept.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ listener.onItemClick(item, true);
+ }
+ });
+ ui.decline.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ listener.onItemClick(item, false);
+ }
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return forums.size();
+ }
+
+ public AvailableForumsItem getItem(int position) {
+ return forums.get(position);
+ }
+
+ public void add(AvailableForumsItem item) {
+ forums.add(item);
+ }
+
+ public void addAll(Collection list) {
+ forums.addAll(list);
+ }
+
+ public void clear() {
+ forums.clear();
+ }
+
+ protected static class AvailableForumViewHolder
+ extends RecyclerView.ViewHolder {
+
+ public final ViewGroup layout;
+ public final TextView name;
+ public final TextView sharedBy;
+ public final Button accept;
+ public final Button decline;
+
+ public AvailableForumViewHolder(View v) {
+ super(v);
+
+ layout = (ViewGroup) v;
+ name = (TextView) v.findViewById(R.id.forumNameView);
+ sharedBy = (TextView) v.findViewById(R.id.sharedByView);
+ accept = (Button) v.findViewById(R.id.acceptButton);
+ decline = (Button) v.findViewById(R.id.declineButton);
+ }
+ }
+
+ private class SortedListCallBacks
+ extends SortedList.Callback {
+
+ @Override
+ public int compare(AvailableForumsItem o1,
+ AvailableForumsItem o2) {
+ return String.CASE_INSENSITIVE_ORDER
+ .compare(o1.getForum().getName(),
+ o2.getForum().getName());
+ }
+
+ @Override
+ public void onInserted(int position, int count) {
+ notifyItemRangeInserted(position, count);
+ }
+
+ @Override
+ public void onRemoved(int position, int count) {
+ notifyItemRangeRemoved(position, count);
+ }
+
+ @Override
+ public void onMoved(int fromPosition, int toPosition) {
+ notifyItemMoved(fromPosition, toPosition);
+ }
+
+ @Override
+ public void onChanged(int position, int count) {
+ notifyItemRangeChanged(position, count);
+ }
+
+ @Override
+ public boolean areContentsTheSame(AvailableForumsItem oldItem,
+ AvailableForumsItem newItem) {
+ return oldItem.getForum().equals(newItem.getForum()) &&
+ oldItem.getContacts().equals(newItem.getContacts());
+ }
+
+ @Override
+ public boolean areItemsTheSame(AvailableForumsItem oldItem,
+ AvailableForumsItem newItem) {
+ return oldItem.getForum().equals(newItem.getForum());
+ }
+ }
+
+
+ interface AvailableForumClickListener {
+ void onItemClick(AvailableForumsItem item, boolean accept);
+ }
+
}
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsItemComparator.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsItemComparator.java
deleted file mode 100644
index c9098edb0..000000000
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsItemComparator.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.briarproject.android.forum;
-
-import java.util.Comparator;
-
-class AvailableForumsItemComparator implements Comparator {
-
- static final AvailableForumsItemComparator INSTANCE =
- new AvailableForumsItemComparator();
-
- public int compare(AvailableForumsItem a, AvailableForumsItem b) {
- if (a == b) return 0;
- String aName = a.getForum().getName();
- String bName = b.getForum().getName();
- return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
- }
-}