Skip to content
Snippets Groups Projects
Verified Commit bcfdd848 authored by Torsten Grote's avatar Torsten Grote
Browse files

Modernize AvailableForumsActivity

Turn list of available forums into a BriarRecyclerView with XML layout.
Allow to respond to forum invitations from the list of available forums.
The user can either accept or decline an invitation.
parent 2cc621ed
No related branches found
No related tags found
No related merge requests found
<?xml version="1.0" encoding="utf-8"?>
<org.briarproject.android.util.BriarRecyclerView
android:id="@+id/availableForumsView"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/listitem_horizontal_margin"
android:layout_marginStart="@dimen/listitem_horizontal_margin"
android:paddingTop="@dimen/listitem_horizontal_margin"
android:background="?attr/selectableItemBackground">
<TextView
android:id="@+id/forumNameView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="2"
android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_size_medium"
tools:text="This is a name of a forum that is available"/>
<TextView
android:id="@+id/sharedByView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/forumNameView"
android:layout_marginBottom="-8dp"
android:paddingTop="@dimen/margin_medium"
android:textColor="@android:color/secondary_text_light"
android:textSize="@dimen/text_size_small"
tools:text="Shared by Megalox"/>
<Button
android:id="@+id/acceptButton"
style="@style/BriarButtonFlat.Positive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_button_accept"
android:layout_below="@+id/sharedByView"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
<Button
android:id="@+id/declineButton"
style="@style/BriarButtonFlat.Negative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_button_decline"
android:layout_below="@+id/sharedByView"
android:layout_toLeftOf="@+id/acceptButton"
android:layout_toStartOf="@+id/acceptButton"/>
<View style="@style/Divider.ForumList"
android:layout_below="@+id/acceptButton"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
</RelativeLayout>
......@@ -102,6 +102,7 @@
<string name="forum_post_hint">Type forum post</string>
<string name="available_forums_title">Available Forums</string>
<string name="forum_joined_toast">Joined Forum</string>
<string name="forum_declined_toast">Forum Invitation Declined</string>
<string name="shared_by_format">Shared by %s</string>
<string name="no_contacts_prompt">You don\'t have any contacts. Add a contact now?</string>
<string name="add_button">Add</string>
......
......@@ -21,14 +21,14 @@ 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 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,
this.contacts = new SortedList<>(ContactListItem.class,
new SortedListCallBacks());
}
......
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<AvailableForumsItem> 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<ContactId> 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<ContactId> 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();
}
});
}
}
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<AvailableForumsAdapter.AvailableForumViewHolder> {
class AvailableForumsAdapter extends ArrayAdapter<AvailableForumsItem> {
private final Context ctx;
private final AvailableForumClickListener listener;
private final SortedList<AvailableForumsItem> 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<AvailableForumsItem>());
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();
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<String> names = new ArrayList<String>();
public AvailableForumViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
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<String> 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);
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();
}
return layout;
public AvailableForumsItem getItem(int position) {
return forums.get(position);
}
public void add(AvailableForumsItem item) {
forums.add(item);
}
public void addAll(Collection<AvailableForumsItem> 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<AvailableForumsItem> {
@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);
}
}
package org.briarproject.android.forum;
import java.util.Comparator;
class AvailableForumsItemComparator implements Comparator<AvailableForumsItem> {
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);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment