mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-21 07:09:56 +01:00
Merge branch '305-new-forum-list' into 'master'
New List of Forums The adapter of the `ForumListFragment` has been changed into a `BriarRecyclerView` and all its code has been adapted and simplified accordingly. All UI of the forum list is now defined in XML layouts. This enabled me to move the snackbar into onCreate(). Before:  After:  See merge request !175
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
|
android:padding="@dimen/margin_activity_horizontal"
|
||||||
android:textSize="@dimen/text_size_large"
|
android:textSize="@dimen/text_size_large"
|
||||||
android:text="@string/no_data"/>
|
android:text="@string/no_data"/>
|
||||||
|
|
||||||
|
|||||||
6
briar-android/res/layout/fragment_forum_list.xml
Normal file
6
briar-android/res/layout/fragment_forum_list.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<org.briarproject.android.util.BriarRecyclerView
|
||||||
|
android:id="@+id/forumList"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
56
briar-android/res/layout/list_item_forum.xml
Normal file
56
briar-android/res/layout/list_item_forum.xml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?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="@color/briar_text_primary"
|
||||||
|
android:textSize="@dimen/text_size_medium"
|
||||||
|
tools:text="This is a name of a forum"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/unreadView"
|
||||||
|
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_toLeftOf="@+id/dateView"
|
||||||
|
android:paddingTop="@dimen/margin_medium"
|
||||||
|
android:paddingBottom="@dimen/listitem_horizontal_margin"
|
||||||
|
android:textColor="@color/briar_text_secondary"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
android:text="@string/no_unread_posts"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dateView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_below="@+id/forumNameView"
|
||||||
|
android:paddingTop="@dimen/margin_medium"
|
||||||
|
android:paddingBottom="@dimen/listitem_horizontal_margin"
|
||||||
|
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
||||||
|
android:layout_marginEnd="@dimen/listitem_horizontal_margin"
|
||||||
|
android:textColor="@color/briar_text_secondary"
|
||||||
|
android:textSize="@dimen/text_size_small"
|
||||||
|
tools:text="Dec 24"/>
|
||||||
|
|
||||||
|
<View style="@style/Divider.ForumList"
|
||||||
|
android:layout_below="@+id/unreadView"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentStart="true"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
<string name="private_message_hint">Type message</string>
|
<string name="private_message_hint">Type message</string>
|
||||||
<string name="message_sent_toast">Message sent</string>
|
<string name="message_sent_toast">Message sent</string>
|
||||||
<string name="forums_title">Forums</string>
|
<string name="forums_title">Forums</string>
|
||||||
<string name="no_forums">No forums</string>
|
<string name="no_forums">You don\'t have any forums.\n\nWhy don\'t you create a new one yourself or ask your contacts to share one with you?</string>
|
||||||
<plurals name="forums_shared">
|
<plurals name="forums_shared">
|
||||||
<item quantity="one">%d forum shared by contacts</item>
|
<item quantity="one">%d forum shared by contacts</item>
|
||||||
<item quantity="other">%d forums shared by contacts</item>
|
<item quantity="other">%d forums shared by contacts</item>
|
||||||
@@ -81,6 +81,11 @@
|
|||||||
<string name="forum_leave">Leave Forum</string>
|
<string name="forum_leave">Leave Forum</string>
|
||||||
<string name="forum_left_toast">Left Forum</string>
|
<string name="forum_left_toast">Left Forum</string>
|
||||||
<string name="no_forum_posts">No posts</string>
|
<string name="no_forum_posts">No posts</string>
|
||||||
|
<string name="no_unread_posts">no unread posts</string>
|
||||||
|
<plurals name="unread_posts">
|
||||||
|
<item quantity="one">%d unread post</item>
|
||||||
|
<item quantity="other">%d unread posts</item>
|
||||||
|
</plurals>
|
||||||
<string name="create_forum_title">New Forum</string>
|
<string name="create_forum_title">New Forum</string>
|
||||||
<string name="choose_forum_name">Choose a name for your forum:</string>
|
<string name="choose_forum_name">Choose a name for your forum:</string>
|
||||||
<string name="create_forum_button">Create Forum</string>
|
<string name="create_forum_button">Create Forum</string>
|
||||||
|
|||||||
@@ -107,6 +107,11 @@
|
|||||||
<item name="android:layout_marginLeft">@dimen/margin_large</item>
|
<item name="android:layout_marginLeft">@dimen/margin_large</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="Divider.ForumList" parent="Divider">
|
||||||
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
<item name="android:layout_height">1dp</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="NavMenuButton" parent="Widget.AppCompat.Button.Borderless.Colored">
|
<style name="NavMenuButton" parent="Widget.AppCompat.Button.Borderless.Colored">
|
||||||
<item name="android:textSize">@dimen/text_size_medium</item>
|
<item name="android:textSize">@dimen/text_size_medium</item>
|
||||||
<item name="android:textColor">@android:color/tertiary_text_light</item>
|
<item name="android:textColor">@android:color/tertiary_text_light</item>
|
||||||
|
|||||||
@@ -1,70 +1,193 @@
|
|||||||
package org.briarproject.android.forum;
|
package org.briarproject.android.forum;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.Intent;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
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.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.briarproject.R;
|
import org.briarproject.R;
|
||||||
import org.briarproject.android.util.LayoutUtils;
|
import org.briarproject.api.forum.Forum;
|
||||||
|
import org.briarproject.api.sync.GroupId;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Collection;
|
||||||
|
|
||||||
import static android.text.TextUtils.TruncateAt.END;
|
import static org.briarproject.android.BriarActivity.GROUP_ID;
|
||||||
import static android.widget.LinearLayout.HORIZONTAL;
|
import static org.briarproject.android.forum.ForumActivity.FORUM_NAME;
|
||||||
import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP_1;
|
|
||||||
|
|
||||||
public class ForumListAdapter extends ArrayAdapter<ForumListItem> {
|
public class ForumListAdapter extends
|
||||||
|
RecyclerView.Adapter<ForumListAdapter.ForumViewHolder> {
|
||||||
|
|
||||||
private final int pad;
|
private SortedList<ForumListItem> forums = new SortedList<>(
|
||||||
|
ForumListItem.class, new SortedList.Callback<ForumListItem>() {
|
||||||
|
@Override
|
||||||
|
public int compare(ForumListItem a, ForumListItem b) {
|
||||||
|
if (a == b) return 0;
|
||||||
|
// The forum with the newest message comes first
|
||||||
|
long aTime = a.getTimestamp(), bTime = b.getTimestamp();
|
||||||
|
if (aTime > bTime) return -1;
|
||||||
|
if (aTime < bTime) return 1;
|
||||||
|
// Break ties by forum name
|
||||||
|
String aName = a.getForum().getName();
|
||||||
|
String bName = b.getForum().getName();
|
||||||
|
return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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(ForumListItem a, ForumListItem b) {
|
||||||
|
return a.getForum().equals(b.getForum()) &&
|
||||||
|
a.getTimestamp() == b.getTimestamp() &&
|
||||||
|
a.getUnreadCount() == b.getUnreadCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areItemsTheSame(ForumListItem a, ForumListItem b) {
|
||||||
|
return a.getForum().equals(b.getForum());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
private final Context ctx;
|
||||||
|
|
||||||
public ForumListAdapter(Context ctx) {
|
public ForumListAdapter(Context ctx) {
|
||||||
super(ctx, android.R.layout.simple_expandable_list_item_1,
|
this.ctx = ctx;
|
||||||
new ArrayList<ForumListItem>());
|
|
||||||
pad = LayoutUtils.getPadding(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public ForumViewHolder onCreateViewHolder(ViewGroup parent,
|
||||||
ForumListItem item = getItem(position);
|
int viewType) {
|
||||||
Context ctx = getContext();
|
|
||||||
Resources res = ctx.getResources();
|
|
||||||
|
|
||||||
LinearLayout layout = new LinearLayout(ctx);
|
View v = LayoutInflater.from(ctx)
|
||||||
layout.setOrientation(HORIZONTAL);
|
.inflate(R.layout.list_item_forum, parent, false);
|
||||||
|
return new ForumViewHolder(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(ForumViewHolder ui, int position) {
|
||||||
|
final ForumListItem item = getItem(position);
|
||||||
|
|
||||||
|
// TODO add avatar. See #337
|
||||||
|
|
||||||
|
// Forum Name
|
||||||
|
ui.name.setText(item.getForum().getName());
|
||||||
|
|
||||||
|
// Unread Count
|
||||||
int unread = item.getUnreadCount();
|
int unread = item.getUnreadCount();
|
||||||
if (unread > 0)
|
if (unread > 0) {
|
||||||
layout.setBackgroundColor(res.getColor(R.color.unread_background));
|
ui.unread.setText(ctx.getResources()
|
||||||
|
.getQuantityString(R.plurals.unread_posts, unread, unread));
|
||||||
TextView name = new TextView(ctx);
|
ui.unread.setTextColor(
|
||||||
name.setLayoutParams(WRAP_WRAP_1);
|
ContextCompat.getColor(ctx, R.color.briar_button_positive));
|
||||||
name.setTextSize(18);
|
|
||||||
name.setSingleLine();
|
|
||||||
name.setEllipsize(END);
|
|
||||||
name.setPadding(pad, pad, pad, pad);
|
|
||||||
String forumName = item.getForum().getName();
|
|
||||||
if (unread > 0) name.setText(forumName + " (" + unread + ")");
|
|
||||||
else name.setText(forumName);
|
|
||||||
layout.addView(name);
|
|
||||||
|
|
||||||
if (item.isEmpty()) {
|
|
||||||
TextView noPosts = new TextView(ctx);
|
|
||||||
noPosts.setPadding(pad, 0, pad, pad);
|
|
||||||
noPosts.setTextColor(res.getColor(R.color.no_posts));
|
|
||||||
noPosts.setText(R.string.no_forum_posts);
|
|
||||||
layout.addView(noPosts);
|
|
||||||
} else {
|
} else {
|
||||||
TextView date = new TextView(ctx);
|
ui.unread.setText(ctx.getString(R.string.no_unread_posts));
|
||||||
date.setPadding(pad, 0, pad, pad);
|
ui.unread.setTextColor(
|
||||||
long timestamp = item.getTimestamp();
|
ContextCompat.getColor(ctx, R.color.briar_text_secondary));
|
||||||
date.setText(DateUtils.getRelativeTimeSpanString(ctx, timestamp));
|
|
||||||
layout.addView(date);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return layout;
|
// Date or "No Posts"
|
||||||
|
if (item.isEmpty()) {
|
||||||
|
ui.date.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
long timestamp = item.getTimestamp();
|
||||||
|
ui.date.setText(
|
||||||
|
DateUtils.getRelativeTimeSpanString(ctx, timestamp));
|
||||||
|
ui.date.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open Forum on Click
|
||||||
|
ui.layout.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent i = new Intent(ctx, ForumActivity.class);
|
||||||
|
Forum f = item.getForum();
|
||||||
|
i.putExtra(GROUP_ID, f.getId().getBytes());
|
||||||
|
i.putExtra(FORUM_NAME, f.getName());
|
||||||
|
ctx.startActivity(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return forums.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForumListItem getItem(int position) {
|
||||||
|
return forums.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public ForumListItem getItem(GroupId g) {
|
||||||
|
for (int i = 0; i < forums.size(); i++) {
|
||||||
|
ForumListItem item = forums.get(i);
|
||||||
|
if (item.getForum().getGroup().getId().equals(g)) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAll(Collection<ForumListItem> items) {
|
||||||
|
forums.addAll(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateItem(ForumListItem item) {
|
||||||
|
ForumListItem oldItem = getItem(item.getForum().getGroup().getId());
|
||||||
|
int position = forums.indexOf(oldItem);
|
||||||
|
forums.updateItemAt(position, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(ForumListItem item) {
|
||||||
|
forums.remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
forums.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return forums.size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class ForumViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
public final ViewGroup layout;
|
||||||
|
public final TextView name;
|
||||||
|
public final TextView unread;
|
||||||
|
public final TextView date;
|
||||||
|
|
||||||
|
public ForumViewHolder(View v) {
|
||||||
|
super(v);
|
||||||
|
|
||||||
|
layout = (ViewGroup) v;
|
||||||
|
name = (TextView) v.findViewById(R.id.forumNameView);
|
||||||
|
unread = (TextView) v.findViewById(R.id.unreadView);
|
||||||
|
date = (TextView) v.findViewById(R.id.dateView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,25 +5,23 @@ import android.os.Bundle;
|
|||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.ListView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import org.briarproject.R;
|
import org.briarproject.R;
|
||||||
import org.briarproject.android.AndroidComponent;
|
import org.briarproject.android.AndroidComponent;
|
||||||
import org.briarproject.android.fragment.BaseEventFragment;
|
import org.briarproject.android.fragment.BaseEventFragment;
|
||||||
import org.briarproject.android.util.ListLoadingProgressBar;
|
import org.briarproject.android.util.BriarRecyclerView;
|
||||||
import org.briarproject.api.db.DbException;
|
import org.briarproject.api.db.DbException;
|
||||||
import org.briarproject.api.db.NoSuchGroupException;
|
import org.briarproject.api.db.NoSuchGroupException;
|
||||||
import org.briarproject.api.event.ContactRemovedEvent;
|
import org.briarproject.api.event.ContactRemovedEvent;
|
||||||
import org.briarproject.api.event.Event;
|
import org.briarproject.api.event.Event;
|
||||||
|
import org.briarproject.api.event.ForumInvitationReceivedEvent;
|
||||||
import org.briarproject.api.event.GroupAddedEvent;
|
import org.briarproject.api.event.GroupAddedEvent;
|
||||||
import org.briarproject.api.event.GroupRemovedEvent;
|
import org.briarproject.api.event.GroupRemovedEvent;
|
||||||
import org.briarproject.api.event.MessageValidatedEvent;
|
import org.briarproject.api.event.MessageValidatedEvent;
|
||||||
@@ -34,26 +32,18 @@ import org.briarproject.api.forum.ForumSharingManager;
|
|||||||
import org.briarproject.api.sync.ClientId;
|
import org.briarproject.api.sync.ClientId;
|
||||||
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.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static android.support.design.widget.Snackbar.LENGTH_INDEFINITE;
|
import static android.support.design.widget.Snackbar.LENGTH_INDEFINITE;
|
||||||
import static android.view.Gravity.CENTER;
|
|
||||||
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.BriarActivity.GROUP_ID;
|
|
||||||
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.MATCH_WRAP_1;
|
|
||||||
|
|
||||||
public class ForumListFragment extends BaseEventFragment implements
|
public class ForumListFragment extends BaseEventFragment implements
|
||||||
AdapterView.OnItemClickListener, View.OnClickListener {
|
View.OnClickListener {
|
||||||
|
|
||||||
public final static String TAG = "ForumListFragment";
|
public final static String TAG = "ForumListFragment";
|
||||||
|
|
||||||
@@ -69,10 +59,8 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TextView empty = null;
|
private BriarRecyclerView list;
|
||||||
private ForumListAdapter adapter = null;
|
private ForumListAdapter adapter;
|
||||||
private ListView list = null;
|
|
||||||
private ListLoadingProgressBar loading = null;
|
|
||||||
private Snackbar snackbar;
|
private Snackbar snackbar;
|
||||||
|
|
||||||
// Fields that are accessed from background threads must be volatile
|
// Fields that are accessed from background threads must be volatile
|
||||||
@@ -86,32 +74,24 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
|
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
LinearLayout layout = new LinearLayout(getContext());
|
View contentView =
|
||||||
layout.setLayoutParams(MATCH_MATCH);
|
inflater.inflate(R.layout.fragment_forum_list, container,
|
||||||
layout.setOrientation(VERTICAL);
|
false);
|
||||||
layout.setGravity(CENTER_HORIZONTAL);
|
|
||||||
|
|
||||||
empty = new TextView(getContext());
|
adapter = new ForumListAdapter(getActivity());
|
||||||
empty.setLayoutParams(MATCH_WRAP_1);
|
|
||||||
empty.setGravity(CENTER);
|
|
||||||
empty.setTextSize(18);
|
|
||||||
empty.setText(R.string.no_forums);
|
|
||||||
empty.setVisibility(GONE);
|
|
||||||
layout.addView(empty);
|
|
||||||
|
|
||||||
adapter = new ForumListAdapter(getContext());
|
list = (BriarRecyclerView) contentView.findViewById(R.id.forumList);
|
||||||
list = new ListView(getContext());
|
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
list.setLayoutParams(MATCH_WRAP_1);
|
|
||||||
list.setAdapter(adapter);
|
list.setAdapter(adapter);
|
||||||
list.setOnItemClickListener(this);
|
list.setEmptyText(getString(R.string.no_forums));
|
||||||
list.setVisibility(GONE);
|
|
||||||
layout.addView(list);
|
|
||||||
|
|
||||||
// Show a progress bar while the list is loading
|
snackbar = Snackbar.make(contentView, "", LENGTH_INDEFINITE);
|
||||||
loading = new ListLoadingProgressBar(getContext());
|
snackbar.getView().setBackgroundResource(R.color.briar_primary);
|
||||||
layout.addView(loading);
|
snackbar.setAction(R.string.show_forums, this);
|
||||||
|
snackbar.setActionTextColor(ContextCompat
|
||||||
|
.getColor(getContext(), R.color.briar_button_positive));
|
||||||
|
|
||||||
return layout;
|
return contentView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -128,13 +108,15 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
snackbar = Snackbar.make(getView(), "", LENGTH_INDEFINITE);
|
loadForumHeaders();
|
||||||
snackbar.getView().setBackgroundResource(R.color.briar_primary);
|
loadAvailableForums();
|
||||||
snackbar.setAction(R.string.show_forums, this);
|
}
|
||||||
snackbar.setActionTextColor(ContextCompat
|
|
||||||
.getColor(getContext(), R.color.briar_button_positive));
|
|
||||||
|
|
||||||
loadHeaders();
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
|
||||||
|
adapter.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -157,30 +139,26 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadHeaders() {
|
private void loadForumHeaders() {
|
||||||
clearHeaders();
|
|
||||||
listener.runOnDbThread(new Runnable() {
|
listener.runOnDbThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
|
// load forums
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
boolean displayedHeaders = false;
|
Collection<ForumListItem> forums = new ArrayList<>();
|
||||||
for (Forum f : forumManager.getForums()) {
|
for (Forum f : forumManager.getForums()) {
|
||||||
try {
|
try {
|
||||||
Collection<ForumPostHeader> headers =
|
Collection<ForumPostHeader> headers =
|
||||||
forumManager.getPostHeaders(f.getId());
|
forumManager.getPostHeaders(f.getId());
|
||||||
displayHeaders(f, headers);
|
forums.add(new ForumListItem(f, headers));
|
||||||
displayedHeaders = true;
|
|
||||||
} catch (NoSuchGroupException e) {
|
} catch (NoSuchGroupException e) {
|
||||||
// Continue
|
// Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int available =
|
displayForumHeaders(forums);
|
||||||
forumSharingManager.getAvailableForums().size();
|
|
||||||
long duration = System.currentTimeMillis() - now;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Full load took " + duration + " ms");
|
LOG.info("Full load took " + duration + " ms");
|
||||||
if (!displayedHeaders) displayEmpty();
|
|
||||||
displayAvailable(available);
|
|
||||||
} 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);
|
||||||
@@ -189,45 +167,35 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearHeaders() {
|
private void displayForumHeaders(final Collection<ForumListItem> forums) {
|
||||||
listener.runOnUiThread(new Runnable() {
|
listener.runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
empty.setVisibility(GONE);
|
if (forums.size() > 0) adapter.addAll(forums);
|
||||||
list.setVisibility(GONE);
|
else list.showData();
|
||||||
snackbar.dismiss();
|
|
||||||
loading.setVisibility(VISIBLE);
|
|
||||||
adapter.clear();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayHeaders(final Forum f,
|
private void loadAvailableForums() {
|
||||||
final Collection<ForumPostHeader> headers) {
|
listener.runOnDbThread(new Runnable() {
|
||||||
listener.runOnUiThread(new Runnable() {
|
|
||||||
public void run() {
|
public void run() {
|
||||||
list.setVisibility(VISIBLE);
|
try {
|
||||||
loading.setVisibility(GONE);
|
long now = System.currentTimeMillis();
|
||||||
// Remove the old item, if any
|
int available =
|
||||||
ForumListItem item = findForum(f.getId());
|
forumSharingManager.getAvailableForums().size();
|
||||||
if (item != null) adapter.remove(item);
|
long duration = System.currentTimeMillis() - now;
|
||||||
// Add a new item
|
if (LOG.isLoggable(INFO))
|
||||||
adapter.add(new ForumListItem(f, headers));
|
LOG.info("Loading available took " + duration + " ms");
|
||||||
adapter.sort(ForumListItemComparator.INSTANCE);
|
displayAvailableForums(available);
|
||||||
selectFirstUnread();
|
} catch (DbException e) {
|
||||||
|
if (LOG.isLoggable(WARNING))
|
||||||
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayEmpty() {
|
private void displayAvailableForums(final int availableCount) {
|
||||||
listener.runOnUiThread(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
empty.setVisibility(VISIBLE);
|
|
||||||
loading.setVisibility(GONE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void displayAvailable(final int availableCount) {
|
|
||||||
listener.runOnUiThread(new Runnable() {
|
listener.runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (availableCount == 0) {
|
if (availableCount == 0) {
|
||||||
@@ -242,42 +210,21 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private ForumListItem findForum(GroupId g) {
|
|
||||||
int count = adapter.getCount();
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
ForumListItem item = adapter.getItem(i);
|
|
||||||
if (item.getForum().getId().equals(g)) return item;
|
|
||||||
}
|
|
||||||
return null; // Not found
|
|
||||||
}
|
|
||||||
|
|
||||||
private void selectFirstUnread() {
|
|
||||||
int firstUnread = -1, count = adapter.getCount();
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
if (adapter.getItem(i).getUnreadCount() > 0) {
|
|
||||||
firstUnread = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (firstUnread == -1) list.setSelection(count - 1);
|
|
||||||
else list.setSelection(firstUnread);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void eventOccurred(Event e) {
|
public void eventOccurred(Event e) {
|
||||||
if (e instanceof ContactRemovedEvent) {
|
if (e instanceof ContactRemovedEvent) {
|
||||||
LOG.info("Contact removed, reloading");
|
LOG.info("Contact removed, reloading available forums");
|
||||||
loadAvailable();
|
loadAvailableForums();
|
||||||
} else if (e instanceof GroupAddedEvent) {
|
} else if (e instanceof GroupAddedEvent) {
|
||||||
GroupAddedEvent g = (GroupAddedEvent) e;
|
GroupAddedEvent g = (GroupAddedEvent) e;
|
||||||
if (g.getGroup().getClientId().equals(forumManager.getClientId())) {
|
if (g.getGroup().getClientId().equals(forumManager.getClientId())) {
|
||||||
LOG.info("Forum added, reloading");
|
LOG.info("Forum added, reloading forums");
|
||||||
loadHeaders();
|
loadForumHeaders();
|
||||||
}
|
}
|
||||||
} else if (e instanceof GroupRemovedEvent) {
|
} else if (e instanceof GroupRemovedEvent) {
|
||||||
GroupRemovedEvent g = (GroupRemovedEvent) e;
|
GroupRemovedEvent g = (GroupRemovedEvent) e;
|
||||||
if (g.getGroup().getClientId().equals(forumManager.getClientId())) {
|
if (g.getGroup().getClientId().equals(forumManager.getClientId())) {
|
||||||
LOG.info("Forum removed, reloading");
|
LOG.info("Forum removed, removing from list");
|
||||||
loadHeaders();
|
removeForum(g.getGroup().getId());
|
||||||
}
|
}
|
||||||
} else if (e instanceof MessageValidatedEvent) {
|
} else if (e instanceof MessageValidatedEvent) {
|
||||||
MessageValidatedEvent m = (MessageValidatedEvent) e;
|
MessageValidatedEvent m = (MessageValidatedEvent) e;
|
||||||
@@ -285,17 +232,15 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
ClientId c = m.getClientId();
|
ClientId c = m.getClientId();
|
||||||
if (c.equals(forumManager.getClientId())) {
|
if (c.equals(forumManager.getClientId())) {
|
||||||
LOG.info("Forum post added, reloading");
|
LOG.info("Forum post added, reloading");
|
||||||
loadHeaders(m.getMessage().getGroupId());
|
loadForumHeaders(m.getMessage().getGroupId());
|
||||||
} else if (!m.isLocal()
|
|
||||||
&& c.equals(forumSharingManager.getClientId())) {
|
|
||||||
LOG.info("Available forums updated, reloading");
|
|
||||||
loadAvailable();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (e instanceof ForumInvitationReceivedEvent) {
|
||||||
|
loadAvailableForums();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadHeaders(final GroupId g) {
|
private void loadForumHeaders(final GroupId g) {
|
||||||
listener.runOnDbThread(new Runnable() {
|
listener.runOnDbThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
@@ -306,9 +251,7 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
long duration = System.currentTimeMillis() - now;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Partial load took " + duration + " ms");
|
LOG.info("Partial load took " + duration + " ms");
|
||||||
displayHeaders(f, headers);
|
updateForum(new ForumListItem(f, headers));
|
||||||
} catch (NoSuchGroupException e) {
|
|
||||||
removeForum(g);
|
|
||||||
} 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);
|
||||||
@@ -317,38 +260,21 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateForum(final ForumListItem item) {
|
||||||
|
listener.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
adapter.updateItem(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void removeForum(final GroupId g) {
|
private void removeForum(final GroupId g) {
|
||||||
listener.runOnUiThread(new Runnable() {
|
listener.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ForumListItem item = findForum(g);
|
ForumListItem item = adapter.getItem(g);
|
||||||
if (item != null) {
|
if (item != null) adapter.remove(item);
|
||||||
adapter.remove(item);
|
|
||||||
if (adapter.isEmpty()) {
|
|
||||||
empty.setVisibility(VISIBLE);
|
|
||||||
list.setVisibility(GONE);
|
|
||||||
} else {
|
|
||||||
selectFirstUnread();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadAvailable() {
|
|
||||||
listener.runOnDbThread(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
int available =
|
|
||||||
forumSharingManager.getAvailableForums().size();
|
|
||||||
long duration = System.currentTimeMillis() - now;
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Loading available took " + duration + " ms");
|
|
||||||
displayAvailable(available);
|
|
||||||
} catch (DbException e) {
|
|
||||||
if (LOG.isLoggable(WARNING))
|
|
||||||
LOG.log(WARNING, e.toString(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -358,13 +284,4 @@ public class ForumListFragment extends BaseEventFragment implements
|
|||||||
startActivity(new Intent(getContext(), AvailableForumsActivity.class));
|
startActivity(new Intent(getContext(), AvailableForumsActivity.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
|
||||||
long id) {
|
|
||||||
Intent i = new Intent(getContext(), ForumActivity.class);
|
|
||||||
Forum f = adapter.getItem(position).getForum();
|
|
||||||
i.putExtra(GROUP_ID, f.getId().getBytes());
|
|
||||||
i.putExtra(FORUM_NAME, f.getName());
|
|
||||||
startActivity(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
package org.briarproject.android.forum;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
public class ForumListItemComparator implements Comparator<ForumListItem> {
|
|
||||||
|
|
||||||
public static final ForumListItemComparator INSTANCE =
|
|
||||||
new ForumListItemComparator();
|
|
||||||
|
|
||||||
public int compare(ForumListItem a, ForumListItem b) {
|
|
||||||
if (a == b) return 0;
|
|
||||||
// The forum with the newest message comes first
|
|
||||||
long aTime = a.getTimestamp(), bTime = b.getTimestamp();
|
|
||||||
if (aTime > bTime) return -1;
|
|
||||||
if (aTime < bTime) return 1;
|
|
||||||
// Break ties by forum name
|
|
||||||
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