diff --git a/briar-android/res/drawable/bubble.xml b/briar-android/res/drawable/bubble.xml index 9b7f37f9f85286fffa9d7421ec7352bc30419920..a00f451ed1cf85fb3f4ae9ec2518f7b240c2f382 100644 --- a/briar-android/res/drawable/bubble.xml +++ b/briar-android/res/drawable/bubble.xml @@ -8,7 +8,8 @@ <padding android:left="@dimen/unread_bubble_padding_horizontal" - android:right="@dimen/unread_bubble_padding_horizontal"/> + android:right="@dimen/unread_bubble_padding_horizontal" + android:bottom="1px"/> <solid android:color="@color/briar_primary"/> diff --git a/briar-android/res/drawable/bubble_problem.xml b/briar-android/res/drawable/bubble_problem.xml new file mode 100644 index 0000000000000000000000000000000000000000..9d27c95966868597028bb7fef6761db186ae9cad --- /dev/null +++ b/briar-android/res/drawable/bubble_problem.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape + xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + + <corners + android:radius="@dimen/unread_bubble_size"/> + + <padding + android:left="@dimen/unread_bubble_padding_horizontal" + android:right="@dimen/unread_bubble_padding_horizontal"/> + + <solid + android:color="@color/briar_gold"/> + + <stroke + android:color="@color/briar_primary" + android:width="@dimen/avatar_border_width"/> + +</shape> + diff --git a/briar-android/res/layout/list_item_available_forum.xml b/briar-android/res/layout/list_item_available_forum.xml index ca9158af1b6c9e13ce67eadf78023c75d4a7c703..536d983e22e42b31b72143aec91c40ec359c7cbf 100644 --- a/briar-android/res/layout/list_item_available_forum.xml +++ b/briar-android/res/layout/list_item_available_forum.xml @@ -11,8 +11,8 @@ <org.briarproject.android.util.TextAvatarView android:id="@+id/avatarView" - android:layout_width="@dimen/avatar_forum_size" - android:layout_height="@dimen/avatar_forum_size" + android:layout_width="@dimen/listitem_picture_frame_size" + android:layout_height="@dimen/listitem_picture_frame_size" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_marginRight="@dimen/listitem_horizontal_margin" diff --git a/briar-android/res/layout/list_item_forum.xml b/briar-android/res/layout/list_item_forum.xml index b513972e1150604698108435cbb43aef8633cd75..171a40859c67555455afbe89f7e902882c39ac6b 100644 --- a/briar-android/res/layout/list_item_forum.xml +++ b/briar-android/res/layout/list_item_forum.xml @@ -1,68 +1,68 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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/listitem_horizontal_margin" android:layout_marginStart="@dimen/listitem_horizontal_margin" - android:paddingTop="@dimen/listitem_horizontal_margin" android:background="?attr/selectableItemBackground"> <org.briarproject.android.util.TextAvatarView android:id="@+id/avatarView" - android:layout_height="@dimen/avatar_forum_size" - android:layout_width="@dimen/avatar_forum_size" - android:layout_marginRight="@dimen/listitem_horizontal_margin" + android:layout_width="@dimen/listitem_picture_frame_size" + android:layout_height="@dimen/listitem_picture_frame_size" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" - /> + android:layout_centerVertical="true" + android:layout_marginRight="@dimen/listitem_horizontal_margin"/> <TextView android:id="@+id/forumNameView" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_marginTop="@dimen/listitem_horizontal_margin" + android:layout_toEndOf="@+id/avatarView" + android:layout_toRightOf="@+id/avatarView" android:maxLines="2" android:textColor="@color/briar_text_primary" android:textSize="@dimen/text_size_medium" - tools:text="This is a name of a forum" - android:layout_alignParentTop="true" - android:layout_toRightOf="@+id/avatarView" - android:layout_toEndOf="@+id/avatarView"/> + 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:paddingTop="@dimen/margin_medium" + android:layout_below="@+id/forumNameView" + android:layout_toEndOf="@+id/avatarView" + android:layout_toRightOf="@+id/avatarView" android:paddingBottom="@dimen/listitem_horizontal_margin" + android:paddingTop="@dimen/margin_medium" android:textColor="@color/briar_text_secondary" android:textSize="@dimen/text_size_small" - android:text="@string/no_unread_posts" - android:layout_below="@+id/forumNameView" - android:layout_toRightOf="@+id/avatarView" - android:layout_toEndOf="@+id/avatarView"/> + tools:text="1337 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_alignParentRight="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:layout_marginRight="@dimen/listitem_horizontal_margin" + android:paddingBottom="@dimen/listitem_horizontal_margin" + android:paddingTop="@dimen/margin_medium" 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"/> + <View + style="@style/Divider.ForumList" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true" + android:layout_below="@+id/unreadView"/> </RelativeLayout> diff --git a/briar-android/res/layout/text_avatar_view.xml b/briar-android/res/layout/text_avatar_view.xml index f9eebbbdfc99482d1556362e796e8f395a5a67f5..211d0f000ee231c52f03fd0067b57bd04ea29424 100644 --- a/briar-android/res/layout/text_avatar_view.xml +++ b/briar-android/res/layout/text_avatar_view.xml @@ -2,14 +2,15 @@ <merge 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"> + xmlns:tools="http://schemas.android.com/tools" + tools:showIn="@layout/list_item_forum"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/avatarBackground" style="@style/BriarAvatar" android:layout_width="@dimen/avatar_forum_size" android:layout_height="@dimen/avatar_forum_size" - android:layout_gravity="center" + android:layout_gravity="bottom|left" android:src="@android:color/transparent" app:civ_fill_color="@color/briar_button_positive"/> @@ -18,13 +19,28 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" + android:layout_marginRight="@dimen/listitem_picture_frame_offset" + android:layout_marginTop="@dimen/listitem_picture_frame_offset" android:maxLength="1" android:shadowColor="@color/forum_avatar_shadow" android:shadowDx="0" android:shadowDy="1.5" android:shadowRadius="1.5" android:textColor="@color/briar_text_primary_inverse" - android:textSize="30sp" + android:textSize="@dimen/avatar_text_size" tools:text="T"/> + <TextView + android:id="@+id/unreadCountView" + android:layout_width="wrap_content" + android:layout_height="@dimen/unread_bubble_size" + android:layout_gravity="right|top" + android:background="@drawable/bubble" + android:gravity="center" + android:minWidth="@dimen/unread_bubble_size" + android:textColor="@color/briar_text_primary_inverse" + android:textSize="@dimen/unread_bubble_text_size" + android:textStyle="bold" + tools:text="12"/> + </merge> diff --git a/briar-android/res/values/color.xml b/briar-android/res/values/color.xml index 14a0938bb09091ae58a05b39bca66308383198b4..8a44a58f3da96298a0c7dcce68df693320999ca3 100644 --- a/briar-android/res/values/color.xml +++ b/briar-android/res/values/color.xml @@ -30,7 +30,7 @@ <color name="briar_text_primary">@color/briar_primary</color> <color name="briar_text_primary_inverse">#ffffff</color> <color name="briar_text_secondary">#333333</color> - <color name="briar_text_tertiary">#333333</color> + <color name="briar_text_tertiary">#FF78909C</color> <color name="briar_button_positive">#06b9ff</color> <color name="briar_button_negative">#ff0000</color> diff --git a/briar-android/res/values/dimens.xml b/briar-android/res/values/dimens.xml index fe0f3ad97f24dd5ecf1e8c1f9ba8d34b3c4ebef4..0a0fc5ce53d27e573c35226632070410fca9b305 100644 --- a/briar-android/res/values/dimens.xml +++ b/briar-android/res/values/dimens.xml @@ -25,11 +25,13 @@ <dimen name="listitem_height_contact_selector">68dp</dimen> <dimen name="listitem_picture_size">48dp</dimen> <dimen name="listitem_picture_size_small">23dp</dimen> - <dimen name="listitem_picture_frame_size">50dp</dimen> + <dimen name="listitem_picture_frame_size">53dp</dimen> + <dimen name="listitem_picture_frame_offset">2dp</dimen> <dimen name="listitem_selectable_picture_size">40dp</dimen> <dimen name="dropdown_picture_size">32dp</dimen> <dimen name="avatar_forum_size">48dp</dimen> <dimen name="avatar_border_width">2dp</dimen> + <dimen name="avatar_text_size">30sp</dimen> <dimen name="unread_bubble_text_size">12sp</dimen> <dimen name="unread_bubble_border_width">2dp</dimen> diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index 2507e5dd0c8dbaa22f421767b42f209889cae285..d237e3260c065b16325c8623de4c0fd73a0b6996 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -80,12 +80,15 @@ <string name="forum_leave">Leave Forum</string> <string name="forum_left_toast">Left Forum</string> <string name="forum_sharing_status">Sharing Status</string> - <string name="no_forum_posts">No posts</string> - <string name="no_unread_posts">no unread posts</string> + <string name="forum_no_posts">No posts</string> <plurals name="unread_posts"> <item quantity="one">%d unread post</item> <item quantity="other">%d unread posts</item> </plurals> + <plurals name="forum_posts"> + <item quantity="one">%d post</item> + <item quantity="other">%d posts</item> + </plurals> <string name="create_forum_title">New Forum</string> <string name="choose_forum_name">Choose a name for your forum:</string> <string name="create_forum_button">Create Forum</string> diff --git a/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java b/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java index de53aab8dafb0520d9be2fee004cec26745d7ff1..34f27ebcf8b8d9bdffc12273bf008abdb7a94340 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java +++ b/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java @@ -19,10 +19,12 @@ import org.briarproject.api.sync.GroupId; import java.util.Collection; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; import static org.briarproject.android.BriarActivity.GROUP_ID; import static org.briarproject.android.forum.ForumActivity.FORUM_NAME; -public class ForumListAdapter extends +class ForumListAdapter extends RecyclerView.Adapter<ForumListAdapter.ForumViewHolder> { private SortedList<ForumListItem> forums = new SortedList<>( @@ -76,7 +78,7 @@ public class ForumListAdapter extends private final Context ctx; - public ForumListAdapter(Context ctx) { + ForumListAdapter(Context ctx) { this.ctx = ctx; } @@ -94,31 +96,36 @@ public class ForumListAdapter extends // Avatar ui.avatar.setText(item.getForum().getName().substring(0, 1)); ui.avatar.setBackgroundBytes(item.getForum().getId().getBytes()); + ui.avatar.setUnreadCount(item.getUnreadCount()); // Forum Name ui.name.setText(item.getForum().getName()); - // Unread Count - int unread = item.getUnreadCount(); - if (unread > 0) { + // Post Count + int postCount = item.getPostCount(); + if (postCount > 0) { ui.unread.setText(ctx.getResources() - .getQuantityString(R.plurals.unread_posts, unread, unread)); + .getQuantityString(R.plurals.forum_posts, postCount, + postCount)); ui.unread.setTextColor( - ContextCompat.getColor(ctx, R.color.briar_button_positive)); + ContextCompat + .getColor(ctx, R.color.briar_text_secondary)); } else { - ui.unread.setText(ctx.getString(R.string.no_unread_posts)); + ui.avatar.setProblem(true); + ui.unread.setText(ctx.getString(R.string.forum_no_posts)); ui.unread.setTextColor( - ContextCompat.getColor(ctx, R.color.briar_text_secondary)); + ContextCompat + .getColor(ctx, R.color.briar_text_tertiary)); } - // Date or "No Posts" + // Date if (item.isEmpty()) { - ui.date.setVisibility(View.GONE); + ui.date.setVisibility(GONE); } else { long timestamp = item.getTimestamp(); ui.date.setText( DateUtils.getRelativeTimeSpanString(ctx, timestamp)); - ui.date.setVisibility(View.VISIBLE); + ui.date.setVisibility(VISIBLE); } // Open Forum on Click @@ -158,7 +165,7 @@ public class ForumListAdapter extends forums.addAll(items); } - public void updateItem(ForumListItem item) { + void updateItem(ForumListItem item) { ForumListItem oldItem = getItem(item.getForum().getGroup().getId()); int position = forums.indexOf(oldItem); forums.updateItemAt(position, item); @@ -176,7 +183,7 @@ public class ForumListAdapter extends return forums.size() == 0; } - protected static class ForumViewHolder extends RecyclerView.ViewHolder { + static class ForumViewHolder extends RecyclerView.ViewHolder { private final ViewGroup layout; private final TextAvatarView avatar; @@ -184,7 +191,7 @@ public class ForumListAdapter extends private final TextView unread; private final TextView date; - public ForumViewHolder(View v) { + ForumViewHolder(View v) { super(v); layout = (ViewGroup) v; diff --git a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java index 9c32079838aa9290bf4c9b19412fc9b67affbcd9..afe61864a7e6cd7b725ad9e4ad395f81dbde2f04 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java +++ b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java @@ -14,8 +14,6 @@ import android.view.View; import android.view.ViewGroup; import org.briarproject.R; -import org.briarproject.android.ActivityComponent; -import org.briarproject.android.AndroidComponent; import org.briarproject.android.fragment.BaseEventFragment; import org.briarproject.android.util.BriarRecyclerView; import org.briarproject.api.db.DbException; diff --git a/briar-android/src/org/briarproject/android/forum/ForumListItem.java b/briar-android/src/org/briarproject/android/forum/ForumListItem.java index f6e55a8a1129f76dcecf4e2aa7ae84abada76014..88a710d4e927719cd2d7ab8b6813f01f0a6a396d 100644 --- a/briar-android/src/org/briarproject/android/forum/ForumListItem.java +++ b/briar-android/src/org/briarproject/android/forum/ForumListItem.java @@ -9,6 +9,7 @@ class ForumListItem { private final Forum forum; private final boolean empty; + private final int postCount; private final long timestamp; private final int unread; @@ -16,6 +17,7 @@ class ForumListItem { this.forum = forum; empty = headers.isEmpty(); if (empty) { + postCount = 0; timestamp = 0; unread = 0; } else { @@ -29,6 +31,7 @@ class ForumListItem { } if (!h.isRead()) unread++; } + this.postCount = headers.size(); this.timestamp = newest.getTimestamp(); this.unread = unread; } @@ -42,6 +45,10 @@ class ForumListItem { return empty; } + int getPostCount() { + return postCount; + } + long getTimestamp() { return timestamp; } diff --git a/briar-android/src/org/briarproject/android/util/TextAvatarView.java b/briar-android/src/org/briarproject/android/util/TextAvatarView.java index 721fc5e91c28d83ea348cc4914b4d96600659c2f..cc4ab91485f01f58350ce663ddcbd81e39a0c502 100644 --- a/briar-android/src/org/briarproject/android/util/TextAvatarView.java +++ b/briar-android/src/org/briarproject/android/util/TextAvatarView.java @@ -1,13 +1,13 @@ package org.briarproject.android.util; import android.content.Context; -import android.content.res.ColorStateList; import android.graphics.Color; -import android.graphics.PorterDuff; +import android.support.v4.content.ContextCompat; import android.support.v7.widget.AppCompatTextView; import android.util.AttributeSet; import android.view.LayoutInflater; import android.widget.FrameLayout; +import android.widget.TextView; import org.briarproject.R; @@ -15,8 +15,10 @@ import de.hdodenhof.circleimageview.CircleImageView; public class TextAvatarView extends FrameLayout { - final private AppCompatTextView textView; - final private CircleImageView backgroundView; + final private AppCompatTextView character; + final private CircleImageView background; + final private TextView badge; + private int unreadCount; public TextAvatarView(Context context, AttributeSet attrs) { super(context, attrs); @@ -25,8 +27,10 @@ public class TextAvatarView extends FrameLayout { .getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater .inflate(R.layout.text_avatar_view, this, true); - textView = (AppCompatTextView) findViewById(R.id.textAvatarView); - backgroundView = (CircleImageView) findViewById(R.id.avatarBackground); + character = (AppCompatTextView) findViewById(R.id.textAvatarView); + background = (CircleImageView) findViewById(R.id.avatarBackground); + badge = (TextView) findViewById(R.id.unreadCountView); + badge.setVisibility(INVISIBLE); } public TextAvatarView(Context context) { @@ -34,7 +38,32 @@ public class TextAvatarView extends FrameLayout { } public void setText(String text) { - textView.setText(text); + character.setText(text); + } + + public void setUnreadCount(int count) { + if (count > 0) { + this.unreadCount = count; + badge.setBackgroundResource(R.drawable.bubble); + badge.setText(String.valueOf(count)); + badge.setTextColor(ContextCompat.getColor(getContext(), R.color.briar_text_primary_inverse)); + badge.setVisibility(VISIBLE); + } else { + badge.setVisibility(INVISIBLE); + } + } + + public void setProblem(boolean problem) { + if (problem) { + badge.setBackgroundResource(R.drawable.bubble_problem); + badge.setText("!"); + badge.setTextColor(ContextCompat.getColor(getContext(), R.color.briar_primary)); + badge.setVisibility(VISIBLE); + } else if (unreadCount > 0) { + setUnreadCount(unreadCount); + } else { + badge.setVisibility(INVISIBLE); + } } public void setBackgroundBytes(byte[] bytes) { @@ -43,7 +72,7 @@ public class TextAvatarView extends FrameLayout { int b = getByte(bytes, 2) * 3 / 4 + 96; int color = Color.rgb(r, g, b); - backgroundView.setFillColor(color); + background.setFillColor(color); } private byte getByte(byte[] bytes, int index) {