mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
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.
This commit is contained in:
6
briar-android/res/layout/activity_available_forums.xml
Normal file
6
briar-android/res/layout/activity_available_forums.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?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"/>
|
||||
60
briar-android/res/layout/list_item_available_forum.xml
Normal file
60
briar-android/res/layout/list_item_available_forum.xml
Normal file
@@ -0,0 +1,60 @@
|
||||
<?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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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<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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<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();
|
||||
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<String> names = new ArrayList<String>();
|
||||
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<String> 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<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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user