diff --git a/briar-android/res/layout/list_item_forum_post.xml b/briar-android/res/layout/list_item_thread.xml similarity index 98% rename from briar-android/res/layout/list_item_forum_post.xml rename to briar-android/res/layout/list_item_thread.xml index 2fe00672178eab9dafc8e92dfd062626fec77260..f788c0ce8e6aff841c4d3f4dcae07e423576966c 100644 --- a/briar-android/res/layout/list_item_forum_post.xml +++ b/briar-android/res/layout/list_item_thread.xml @@ -1,12 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout + android:id="@+id/layout" 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:id="@+id/forum_cell" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal"> + android:orientation="horizontal" + android:baselineAligned="false"> <RelativeLayout android:layout_width="wrap_content" diff --git a/briar-android/res/layout/list_item_thread_notice.xml b/briar-android/res/layout/list_item_thread_notice.xml new file mode 100644 index 0000000000000000000000000000000000000000..2beecd1f2aabf4c2a2b209974e6d383268e3d8b1 --- /dev/null +++ b/briar-android/res/layout/list_item_thread_notice.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + android:id="@+id/layout" + 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:layout_marginLeft="@dimen/margin_medium" + android:baselineAligned="false" + android:orientation="vertical"> + + <View + android:id="@+id/top_divider" + style="@style/Divider.ForumList" + android:layout_width="match_parent" + android:layout_height="@dimen/margin_separator"/> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/margin_small" + android:layout_marginLeft="@dimen/margin_medium" + android:layout_marginRight="@dimen/margin_medium" + android:layout_marginTop="@dimen/margin_medium" + android:orientation="horizontal"> + + <org.briarproject.android.view.AuthorView + android:id="@+id/author" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:persona="commenter"/> + + <org.thoughtcrime.securesms.components.emoji.EmojiTextView + android:id="@+id/text" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginLeft="@dimen/margin_medium" + android:gravity="center_vertical" + android:textColor="@color/briar_text_secondary" + android:textIsSelectable="true" + android:textSize="@dimen/text_size_medium" + android:textStyle="italic" + tools:text="@string/groups_member_joined"/> + + </LinearLayout> + +</LinearLayout> diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index 878b281e48a5de9ec154e3b7b0ca69a2bf8467fe..132cea768dd5f12ffc8b3c4265d99fb5354eadeb 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -166,6 +166,7 @@ <string name="groups_invite_members">Invite Members</string> <string name="groups_leave">Leave Group</string> <string name="groups_dissolve">Dissolve Group</string> + <string name="groups_member_joined">joined the group.</string> <!-- Private Group Invitations --> <string name="groups_invitations_title">Group Invitations</string> diff --git a/briar-android/src/org/briarproject/android/ActivityModule.java b/briar-android/src/org/briarproject/android/ActivityModule.java index 174a5c94668a193735716965d889c99644626b21..6550d1752b6b05fbd484da2f97d506bfd332fb91 100644 --- a/briar-android/src/org/briarproject/android/ActivityModule.java +++ b/briar-android/src/org/briarproject/android/ActivityModule.java @@ -120,6 +120,7 @@ public class ActivityModule { @Provides protected GroupController provideGroupController( GroupControllerImpl groupController) { + activity.addLifecycleController(groupController); return groupController; } diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java index 307a7c5e158407d4a0cd173974607da181716181..31816fa8fea8fc2fb4f9678591b507416c827c84 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java +++ b/briar-android/src/org/briarproject/android/forum/ForumActivity.java @@ -18,8 +18,9 @@ import android.widget.Toast; import org.briarproject.R; import org.briarproject.android.ActivityComponent; import org.briarproject.android.controller.handler.UiResultExceptionHandler; -import org.briarproject.android.sharing.ShareForumActivity; import org.briarproject.android.sharing.ForumSharingStatusActivity; +import org.briarproject.android.sharing.ShareForumActivity; +import org.briarproject.android.threaded.ThreadItemAdapter; import org.briarproject.android.threaded.ThreadListActivity; import org.briarproject.android.threaded.ThreadListController; import org.briarproject.api.db.DbException; @@ -35,7 +36,7 @@ import static android.widget.Toast.LENGTH_SHORT; import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH; public class ForumActivity extends - ThreadListActivity<Forum, ForumItem, ForumPostHeader, NestedForumAdapter> { + ThreadListActivity<Forum, ForumItem, ForumPostHeader, ThreadItemAdapter<ForumItem>> { private static final int REQUEST_FORUM_SHARED = 3; @@ -74,9 +75,9 @@ public class ForumActivity extends } @Override - protected NestedForumAdapter createAdapter( + protected ThreadItemAdapter<ForumItem> createAdapter( LinearLayoutManager layoutManager) { - return new NestedForumAdapter(this, layoutManager); + return new ThreadItemAdapter<>(this, layoutManager); } @Override diff --git a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java b/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java index 5da9ee98c7cda5e7812b040470857e1e4707d259..25d8328464377f8bff53ea5b33e018265db19538 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java +++ b/briar-android/src/org/briarproject/android/forum/ForumControllerImpl.java @@ -88,8 +88,8 @@ public class ForumControllerImpl } @Override - protected String loadMessageBody(MessageId id) throws DbException { - return StringUtils.fromUtf8(forumManager.getPostBody(id)); + protected String loadMessageBody(ForumPostHeader h) throws DbException { + return StringUtils.fromUtf8(forumManager.getPostBody(h.getId())); } @Override diff --git a/briar-android/src/org/briarproject/android/forum/NestedForumAdapter.java b/briar-android/src/org/briarproject/android/forum/NestedForumAdapter.java deleted file mode 100644 index 08d68b961301b4883a01e5c1f36ac6eb5ea83795..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/forum/NestedForumAdapter.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.briarproject.android.forum; - -import android.support.annotation.UiThread; -import android.support.v7.widget.LinearLayoutManager; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import org.briarproject.R; -import org.briarproject.android.threaded.ThreadItemAdapter; - -@UiThread -class NestedForumAdapter extends ThreadItemAdapter<ForumItem> { - - NestedForumAdapter(ThreadItemListener<ForumItem> listener, - LinearLayoutManager layoutManager) { - super(listener, layoutManager); - } - - @Override - public NestedForumHolder onCreateViewHolder(ViewGroup parent, - int viewType) { - View v = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.list_item_forum_post, parent, false); - return new NestedForumHolder(v); - } - -} diff --git a/briar-android/src/org/briarproject/android/forum/NestedForumHolder.java b/briar-android/src/org/briarproject/android/forum/NestedForumHolder.java deleted file mode 100644 index b73558ff5d668c1adf37f0e8e69a9f971411967c..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/forum/NestedForumHolder.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.briarproject.android.forum; - -import android.view.View; - -import org.briarproject.android.threaded.ThreadItemViewHolder; - -public class NestedForumHolder extends ThreadItemViewHolder<ForumItem> { - - public NestedForumHolder(View v) { - super(v); - } - -} diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java index 6b34d19cd9dc87043eb0ee7514d3b76afb3e9db1..8d61bbff83dd964ed230113e0053f7b4f1027279 100644 --- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java +++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java @@ -2,6 +2,7 @@ package org.briarproject.android.privategroup.conversation; import android.support.annotation.Nullable; +import org.briarproject.R; import org.briarproject.android.api.AndroidNotificationManager; import org.briarproject.android.controller.handler.ResultExceptionHandler; import org.briarproject.android.threaded.ThreadListControllerImpl; @@ -17,6 +18,7 @@ import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.privategroup.GroupMessage; import org.briarproject.api.privategroup.GroupMessageFactory; import org.briarproject.api.privategroup.GroupMessageHeader; +import org.briarproject.api.privategroup.JoinMessageHeader; import org.briarproject.api.privategroup.PrivateGroup; import org.briarproject.api.privategroup.PrivateGroupManager; import org.briarproject.api.sync.MessageId; @@ -90,8 +92,13 @@ public class GroupControllerImpl extends } @Override - protected String loadMessageBody(MessageId id) throws DbException { - return privateGroupManager.getMessageBody(id); + protected String loadMessageBody(GroupMessageHeader header) + throws DbException { + if (header instanceof JoinMessageHeader) { + return listener.getApplicationContext() + .getString(R.string.groups_member_joined); + } + return privateGroupManager.getMessageBody(header.getId()); } @Override @@ -162,6 +169,9 @@ public class GroupControllerImpl extends @Override protected GroupMessageItem buildItem(GroupMessageHeader header, String body) { + if (header instanceof JoinMessageHeader) { + return new JoinMessageItem(header, body); + } return new GroupMessageItem(header, body); } diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageAdapter.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageAdapter.java index 19ee14adce62158808c7f795e9eb505ec889cd2f..2a9c75a009f1d4e2c79851713dc1256a2ae74236 100644 --- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageAdapter.java +++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageAdapter.java @@ -7,7 +7,9 @@ import android.view.View; import android.view.ViewGroup; import org.briarproject.R; +import org.briarproject.android.threaded.BaseThreadItemViewHolder; import org.briarproject.android.threaded.ThreadItemAdapter; +import org.briarproject.android.threaded.ThreadItemViewHolder; @UiThread public class GroupMessageAdapter extends ThreadItemAdapter<GroupMessageItem> { @@ -18,11 +20,23 @@ public class GroupMessageAdapter extends ThreadItemAdapter<GroupMessageItem> { } @Override - public GroupMessageViewHolder onCreateViewHolder(ViewGroup parent, - int viewType) { + public int getItemViewType(int position) { + GroupMessageItem item = getVisibleItem(position); + if (item instanceof JoinMessageItem) { + return R.layout.list_item_thread_notice; + } + return R.layout.list_item_thread; + } + + @Override + public BaseThreadItemViewHolder<GroupMessageItem> onCreateViewHolder( + ViewGroup parent, int type) { View v = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.list_item_forum_post, parent, false); - return new GroupMessageViewHolder(v); + .inflate(type, parent, false); + if (type == R.layout.list_item_thread_notice) { + return new BaseThreadItemViewHolder<>(v); + } + return new ThreadItemViewHolder<>(v); } } diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageItem.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageItem.java index 7bde4a8bbcf183f06f275d7fbb0c49395259aea1..b961fd3f6bd5d34d3c30b4b280015a74dd78f3d5 100644 --- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageItem.java +++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageItem.java @@ -8,7 +8,7 @@ import org.briarproject.api.sync.MessageId; class GroupMessageItem extends ThreadItem { - GroupMessageItem(MessageId messageId, MessageId parentId, + private GroupMessageItem(MessageId messageId, MessageId parentId, String text, long timestamp, Author author, Status status, boolean isRead) { super(messageId, parentId, text, timestamp, author, status, isRead); diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageViewHolder.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageViewHolder.java deleted file mode 100644 index 11825b8056e6ee3002338956a6599c2a4b949b21..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupMessageViewHolder.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.briarproject.android.privategroup.conversation; - -import android.view.View; - -import org.briarproject.android.threaded.ThreadItemViewHolder; - -public class GroupMessageViewHolder - extends ThreadItemViewHolder<GroupMessageItem> { - - public GroupMessageViewHolder(View v) { - super(v); - } - -} diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItem.java b/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItem.java new file mode 100644 index 0000000000000000000000000000000000000000..e21399127a16c29b07449b15f159da11f08ffa3c --- /dev/null +++ b/briar-android/src/org/briarproject/android/privategroup/conversation/JoinMessageItem.java @@ -0,0 +1,22 @@ +package org.briarproject.android.privategroup.conversation; + +import org.briarproject.api.privategroup.GroupMessageHeader; + +class JoinMessageItem extends GroupMessageItem { + + JoinMessageItem(GroupMessageHeader h, + String text) { + super(h, text); + } + + @Override + public int getLevel() { + return 0; + } + + @Override + public boolean hasDescendants() { + return false; + } + +} diff --git a/briar-android/src/org/briarproject/android/threaded/BaseThreadItemViewHolder.java b/briar-android/src/org/briarproject/android/threaded/BaseThreadItemViewHolder.java new file mode 100644 index 0000000000000000000000000000000000000000..47ed3502fa1dbb7b1b546c5167864273784f524a --- /dev/null +++ b/briar-android/src/org/briarproject/android/threaded/BaseThreadItemViewHolder.java @@ -0,0 +1,122 @@ +package org.briarproject.android.threaded; + +import android.animation.Animator; +import android.animation.ArgbEvaluator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.drawable.ColorDrawable; +import android.support.annotation.CallSuper; +import android.support.annotation.UiThread; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.briarproject.R; +import org.briarproject.android.threaded.ThreadItemAdapter.ThreadItemListener; +import org.briarproject.android.view.AuthorView; +import org.briarproject.api.nullsafety.NotNullByDefault; +import org.briarproject.util.StringUtils; + +@UiThread +@NotNullByDefault +public class BaseThreadItemViewHolder<I extends ThreadItem> + extends RecyclerView.ViewHolder { + + private final static int ANIMATION_DURATION = 5000; + + private final ViewGroup layout; + private final TextView textView; + private final AuthorView author; + private final View topDivider; + + public BaseThreadItemViewHolder(View v) { + super(v); + + layout = (ViewGroup) v.findViewById(R.id.layout); + textView = (TextView) v.findViewById(R.id.text); + author = (AuthorView) v.findViewById(R.id.author); + topDivider = v.findViewById(R.id.top_divider); + } + + // TODO improve encapsulation, so we don't need to pass the adapter here + @CallSuper + public void bind(final ThreadItemAdapter<I> adapter, + final ThreadItemListener<I> listener, final I item, int pos) { + + textView.setText(StringUtils.trim(item.getText())); + + if (pos == 0) { + topDivider.setVisibility(View.INVISIBLE); + } else { + topDivider.setVisibility(View.VISIBLE); + } + + author.setAuthor(item.getAuthor()); + author.setDate(item.getTimestamp()); + author.setAuthorStatus(item.getStatus()); + + if (item.equals(adapter.getReplyItem())) { + layout.setBackgroundColor(ContextCompat + .getColor(getContext(), R.color.forum_cell_highlight)); + } else if (item.equals(adapter.getAddedItem())) { + layout.setBackgroundColor(ContextCompat + .getColor(getContext(), R.color.forum_cell_highlight)); + animateFadeOut(adapter, adapter.getAddedItem()); + adapter.clearAddedItem(); + } else { + layout.setBackgroundColor(ContextCompat + .getColor(getContext(), R.color.window_background)); + } + } + + private void animateFadeOut(final ThreadItemAdapter<I> adapter, + final I addedItem) { + + setIsRecyclable(false); + ValueAnimator anim = new ValueAnimator(); + adapter.addAnimatingItem(addedItem, anim); + ColorDrawable viewColor = (ColorDrawable) layout.getBackground(); + anim.setIntValues(viewColor.getColor(), ContextCompat + .getColor(getContext(), R.color.window_background)); + anim.setEvaluator(new ArgbEvaluator()); + anim.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + setIsRecyclable(true); + adapter.removeAnimatingItem(addedItem); + } + + @Override + public void onAnimationCancel(Animator animation) { + setIsRecyclable(true); + adapter.removeAnimatingItem(addedItem); + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + layout.setBackgroundColor( + (Integer) valueAnimator.getAnimatedValue()); + } + }); + anim.setDuration(ANIMATION_DURATION); + anim.start(); + } + + protected Context getContext() { + return textView.getContext(); + } + +} diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadItem.java b/briar-android/src/org/briarproject/android/threaded/ThreadItem.java index a5a22075995246e5859671bc7b64995324bb75ea..c4281e9ac1a5ea1b4f96739403151ea868fa738d 100644 --- a/briar-android/src/org/briarproject/android/threaded/ThreadItem.java +++ b/briar-android/src/org/briarproject/android/threaded/ThreadItem.java @@ -1,13 +1,18 @@ package org.briarproject.android.threaded; +import android.support.annotation.UiThread; + import org.briarproject.api.clients.MessageTree.MessageNode; import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author.Status; import org.briarproject.api.sync.MessageId; +import javax.annotation.concurrent.NotThreadSafe; + import static org.briarproject.android.threaded.ThreadItemAdapter.UNDEFINED; -/* This class is not thread safe */ +@UiThread +@NotThreadSafe public abstract class ThreadItem implements MessageNode { private final MessageId messageId; diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadItemAdapter.java b/briar-android/src/org/briarproject/android/threaded/ThreadItemAdapter.java index c8ab7f2ba0bf173f8688939167c40db894683663..9e93f8f0714cf10635060ff28213e154e646c9be 100644 --- a/briar-android/src/org/briarproject/android/threaded/ThreadItemAdapter.java +++ b/briar-android/src/org/briarproject/android/threaded/ThreadItemAdapter.java @@ -5,7 +5,11 @@ import android.support.annotation.Nullable; import android.support.annotation.UiThread; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import org.briarproject.R; import org.briarproject.android.util.VersionedAdapter; import org.briarproject.api.sync.MessageId; @@ -17,8 +21,8 @@ import java.util.Map; import static android.support.v7.widget.RecyclerView.NO_POSITION; -public abstract class ThreadItemAdapter<I extends ThreadItem> - extends RecyclerView.Adapter<ThreadItemViewHolder<I>> +public class ThreadItemAdapter<I extends ThreadItem> + extends RecyclerView.Adapter<BaseThreadItemViewHolder<I>> implements VersionedAdapter { static final int UNDEFINED = -1; @@ -42,7 +46,15 @@ public abstract class ThreadItemAdapter<I extends ThreadItem> } @Override - public void onBindViewHolder(ThreadItemViewHolder<I> ui, int position) { + public BaseThreadItemViewHolder<I> onCreateViewHolder( + ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.list_item_thread, parent, false); + return new ThreadItemViewHolder<>(v); + } + + @Override + public void onBindViewHolder(BaseThreadItemViewHolder<I> ui, int position) { I item = getVisibleItem(position); if (item == null) return; listener.onItemVisible(item); diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadItemViewHolder.java b/briar-android/src/org/briarproject/android/threaded/ThreadItemViewHolder.java index 0b5a5ddc5b74cc34bee5bb6d63b2534ce2aa0227..c59eac8a48305ecc48a417a1b536ee5fd0c55738 100644 --- a/briar-android/src/org/briarproject/android/threaded/ThreadItemViewHolder.java +++ b/briar-android/src/org/briarproject/android/threaded/ThreadItemViewHolder.java @@ -1,45 +1,30 @@ package org.briarproject.android.threaded; -import android.animation.Animator; -import android.animation.ArgbEvaluator; -import android.animation.ValueAnimator; -import android.content.Context; -import android.graphics.drawable.ColorDrawable; import android.support.annotation.UiThread; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.RecyclerView; import android.view.View; -import android.view.ViewGroup; import android.widget.TextView; import org.briarproject.R; import org.briarproject.android.threaded.ThreadItemAdapter.ThreadItemListener; -import org.briarproject.android.view.AuthorView; -import org.briarproject.util.StringUtils; +import org.briarproject.api.nullsafety.NotNullByDefault; import static android.view.View.GONE; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; @UiThread -public abstract class ThreadItemViewHolder<I extends ThreadItem> - extends RecyclerView.ViewHolder { +@NotNullByDefault +public class ThreadItemViewHolder<I extends ThreadItem> + extends BaseThreadItemViewHolder<I> { - private final static int ANIMATION_DURATION = 5000; - - private final TextView textView, lvlText, repliesText; - private final AuthorView author; + private final TextView lvlText, repliesText; private final View[] lvls; private final View chevron, replyButton; - private final ViewGroup cell; - private final View topDivider; public ThreadItemViewHolder(View v) { super(v); - textView = (TextView) v.findViewById(R.id.text); lvlText = (TextView) v.findViewById(R.id.nested_line_text); - author = (AuthorView) v.findViewById(R.id.author); repliesText = (TextView) v.findViewById(R.id.replies); int[] nestedLineIds = { R.id.nested_line_1, R.id.nested_line_2, R.id.nested_line_3, @@ -51,21 +36,13 @@ public abstract class ThreadItemViewHolder<I extends ThreadItem> } chevron = v.findViewById(R.id.chevron); replyButton = v.findViewById(R.id.btn_reply); - cell = (ViewGroup) v.findViewById(R.id.forum_cell); - topDivider = v.findViewById(R.id.top_divider); } // TODO improve encapsulation, so we don't need to pass the adapter here + @Override public void bind(final ThreadItemAdapter<I> adapter, final ThreadItemListener<I> listener, final I item, int pos) { - - textView.setText(StringUtils.trim(item.getText())); - - if (pos == 0) { - topDivider.setVisibility(View.INVISIBLE); - } else { - topDivider.setVisibility(View.VISIBLE); - } + super.bind(adapter, listener, item, pos); for (int i = 0; i < lvls.length; i++) { lvls[i].setVisibility(i < item.getLevel() ? VISIBLE : GONE); @@ -76,9 +53,6 @@ public abstract class ThreadItemViewHolder<I extends ThreadItem> } else { lvlText.setVisibility(GONE); } - author.setAuthor(item.getAuthor()); - author.setDate(item.getTimestamp()); - author.setAuthorStatus(item.getStatus()); int replies = adapter.getReplyCount(item); if (replies == 0) { @@ -110,18 +84,6 @@ public abstract class ThreadItemViewHolder<I extends ThreadItem> } else { chevron.setVisibility(INVISIBLE); } - if (item.equals(adapter.getReplyItem())) { - cell.setBackgroundColor(ContextCompat - .getColor(getContext(), R.color.forum_cell_highlight)); - } else if (item.equals(adapter.getAddedItem())) { - cell.setBackgroundColor(ContextCompat - .getColor(getContext(), R.color.forum_cell_highlight)); - animateFadeOut(adapter, adapter.getAddedItem()); - adapter.clearAddedItem(); - } else { - cell.setBackgroundColor(ContextCompat - .getColor(getContext(), R.color.window_background)); - } replyButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -131,52 +93,4 @@ public abstract class ThreadItemViewHolder<I extends ThreadItem> }); } - private void animateFadeOut(final ThreadItemAdapter<I> adapter, - final I addedItem) { - - setIsRecyclable(false); - ValueAnimator anim = new ValueAnimator(); - adapter.addAnimatingItem(addedItem, anim); - ColorDrawable viewColor = (ColorDrawable) cell.getBackground(); - anim.setIntValues(viewColor.getColor(), ContextCompat - .getColor(getContext(), R.color.window_background)); - anim.setEvaluator(new ArgbEvaluator()); - anim.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - - } - - @Override - public void onAnimationEnd(Animator animation) { - setIsRecyclable(true); - adapter.removeAnimatingItem(addedItem); - } - - @Override - public void onAnimationCancel(Animator animation) { - setIsRecyclable(true); - adapter.removeAnimatingItem(addedItem); - } - - @Override - public void onAnimationRepeat(Animator animation) { - - } - }); - anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator valueAnimator) { - cell.setBackgroundColor( - (Integer) valueAnimator.getAnimatedValue()); - } - }); - anim.setDuration(ANIMATION_DURATION); - anim.start(); - } - - private Context getContext() { - return textView.getContext(); - } - } diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadListController.java b/briar-android/src/org/briarproject/android/threaded/ThreadListController.java index f2e7570a820d89f66cf7e3452d74b3a1a4256514..43ce1d5c283dbe154b17e66976fef62451a4ee02 100644 --- a/briar-android/src/org/briarproject/android/threaded/ThreadListController.java +++ b/briar-android/src/org/briarproject/android/threaded/ThreadListController.java @@ -1,5 +1,6 @@ package org.briarproject.android.threaded; +import android.content.Context; import android.support.annotation.Nullable; import android.support.annotation.UiThread; @@ -39,6 +40,8 @@ public interface ThreadListController<G extends NamedGroup, I extends ThreadItem @UiThread void onGroupRemoved(); + + Context getApplicationContext(); } } diff --git a/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java b/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java index d584d87045ed046f1af4b2f4161cc40db0ecfed7..cf6ffb8d6cfc33657d7b0905da404e9e78a19958 100644 --- a/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java +++ b/briar-android/src/org/briarproject/android/threaded/ThreadListControllerImpl.java @@ -52,7 +52,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T private volatile GroupId groupId; - protected ThreadListListener<H> listener; + protected volatile ThreadListListener<H> listener; protected ThreadListControllerImpl(@DatabaseExecutor Executor dbExecutor, LifecycleManager lifecycleManager, IdentityManager identityManager, @@ -159,7 +159,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T for (H header : headers) { if (!bodyCache.containsKey(header.getId())) { bodyCache.put(header.getId(), - loadMessageBody(header.getId())); + loadMessageBody(header)); } } duration = System.currentTimeMillis() - now; @@ -181,7 +181,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T protected abstract Collection<H> loadHeaders() throws DbException; @DatabaseExecutor - protected abstract String loadMessageBody(MessageId id) throws DbException; + protected abstract String loadMessageBody(H header) throws DbException; @Override public void loadItem(final H header, @@ -193,7 +193,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T long now = System.currentTimeMillis(); String body; if (!bodyCache.containsKey(header.getId())) { - body = loadMessageBody(header.getId()); + body = loadMessageBody(header); bodyCache.put(header.getId(), body); } else { body = bodyCache.get(header.getId()); diff --git a/briar-android/test/java/org/briarproject/android/forum/ForumActivityTest.java b/briar-android/test/java/org/briarproject/android/forum/ForumActivityTest.java index 991f59f0f26dca492ff6b7204871430f0c0d4928..cedacc77d08850c7dc891bd4647f215150bb9f5f 100644 --- a/briar-android/test/java/org/briarproject/android/forum/ForumActivityTest.java +++ b/briar-android/test/java/org/briarproject/android/forum/ForumActivityTest.java @@ -8,6 +8,7 @@ import org.briarproject.BuildConfig; import org.briarproject.TestUtils; import org.briarproject.android.TestBriarApplication; import org.briarproject.android.controller.handler.UiResultExceptionHandler; +import org.briarproject.android.threaded.ThreadItemAdapter; import org.briarproject.api.db.DbException; import org.briarproject.api.identity.Author; import org.briarproject.api.identity.AuthorId; @@ -111,7 +112,7 @@ public class ForumActivityTest { List<ForumItem> dummyData = getDummyData(); verify(mc, times(1)).loadItems(rc.capture()); rc.getValue().onResult(dummyData); - NestedForumAdapter adapter = forumActivity.getAdapter(); + ThreadItemAdapter<ForumItem> adapter = forumActivity.getAdapter(); Assert.assertNotNull(adapter); // Cascade close assertEquals(6, adapter.getItemCount()); diff --git a/briar-android/test/java/org/briarproject/android/forum/TestForumActivity.java b/briar-android/test/java/org/briarproject/android/forum/TestForumActivity.java index 806fee299bf73a5bb23a034dfd8541765b1b29d3..a77a88cc156c4771d0da6689eca875539f624037 100644 --- a/briar-android/test/java/org/briarproject/android/forum/TestForumActivity.java +++ b/briar-android/test/java/org/briarproject/android/forum/TestForumActivity.java @@ -3,6 +3,7 @@ package org.briarproject.android.forum; import org.briarproject.android.ActivityModule; import org.briarproject.android.controller.BriarController; import org.briarproject.android.controller.BriarControllerImpl; +import org.briarproject.android.threaded.ThreadItemAdapter; import org.mockito.Mockito; /** @@ -15,7 +16,7 @@ public class TestForumActivity extends ForumActivity { return forumController; } - public NestedForumAdapter getAdapter() { + public ThreadItemAdapter<ForumItem> getAdapter() { return adapter; } diff --git a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java index 8910913538a21ead4a38be84208f6aae53e06c62..caf8b81ae4a0614cf53129525e9e13faaadae2c4 100644 --- a/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java +++ b/briar-core/src/org/briarproject/privategroup/PrivateGroupManagerImpl.java @@ -26,7 +26,6 @@ import org.briarproject.api.sync.Message; import org.briarproject.api.sync.MessageId; import org.briarproject.clients.BdfIncomingMessageHook; import org.briarproject.util.StringUtils; -import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; @@ -236,10 +235,6 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements @Override public String getMessageBody(MessageId m) throws DbException { try { - // TODO remove - if (clientHelper.getMessageMetadataAsDictionary(m).getLong(KEY_TYPE) != POST.getInt()) - return "new member joined"; - // type(0), member_name(1), member_public_key(2), parent_id(3), // previous_message_id(4), content(5), signature(6) return clientHelper.getMessageAsList(m).getString(5);