Add small avatars to boosted toots and to notifications.

This commit is contained in:
Ivan Kupalov 2017-07-14 08:06:32 +03:00
parent 38db48c7cb
commit 240fb372ba
5 changed files with 153 additions and 50 deletions

View file

@ -16,6 +16,8 @@
package com.keylesspalace.tusky.adapter; package com.keylesspalace.tusky.adapter;
import android.content.Context; import android.content.Context;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
@ -32,9 +34,11 @@ import android.widget.TextView;
import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.entity.Notification; import com.keylesspalace.tusky.entity.Notification;
import com.keylesspalace.tusky.interfaces.StatusActionListener; import com.keylesspalace.tusky.interfaces.StatusActionListener;
import com.keylesspalace.tusky.view.RoundedTransformation;
import com.keylesspalace.tusky.viewdata.NotificationViewData; import com.keylesspalace.tusky.viewdata.NotificationViewData;
import com.keylesspalace.tusky.viewdata.StatusViewData; import com.keylesspalace.tusky.viewdata.StatusViewData;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import com.varunest.sparkbutton.helpers.Utils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -107,6 +111,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
holder.setMessage(type, notification.getAccount().getDisplayName(), holder.setMessage(type, notification.getAccount().getDisplayName(),
notification.getStatusViewData()); notification.getStatusViewData());
holder.setupButtons(notificationActionListener, notification.getAccount().id); holder.setupButtons(notificationActionListener, notification.getAccount().id);
holder.setAvatars(notification.getStatusViewData().getAvatar(),
notification.getAccount().avatar);
break; break;
} }
case FOLLOW: { case FOLLOW: {
@ -216,6 +222,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
Picasso.with(context) Picasso.with(context)
.load(avatarUrl) .load(avatarUrl)
.fit()
.transform(new RoundedTransformation(7, 0))
.placeholder(R.drawable.avatar_default) .placeholder(R.drawable.avatar_default)
.error(R.drawable.avatar_error) .error(R.drawable.avatar_error)
.into(avatar); .into(avatar);
@ -236,6 +244,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
private ImageView icon; private ImageView icon;
private TextView statusContent; private TextView statusContent;
private ViewGroup container; private ViewGroup container;
private ImageView statusAvatar;
private ImageView notificationAvatar;
StatusNotificationViewHolder(View itemView) { StatusNotificationViewHolder(View itemView) {
super(itemView); super(itemView);
@ -243,6 +253,12 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
icon = (ImageView) itemView.findViewById(R.id.notification_icon); icon = (ImageView) itemView.findViewById(R.id.notification_icon);
statusContent = (TextView) itemView.findViewById(R.id.notification_content); statusContent = (TextView) itemView.findViewById(R.id.notification_content);
container = (ViewGroup) itemView.findViewById(R.id.notification_container); container = (ViewGroup) itemView.findViewById(R.id.notification_container);
statusAvatar = (ImageView) itemView.findViewById(R.id.notification_status_avatar);
notificationAvatar = (ImageView)
itemView.findViewById(R.id.notification_notification_avatar);
int darkerFilter = Color.rgb(123, 123, 123);
statusAvatar.setColorFilter(darkerFilter, PorterDuff.Mode.MULTIPLY);
notificationAvatar.setColorFilter(darkerFilter, PorterDuff.Mode.MULTIPLY);
} }
void setMessage(Notification.Type type, String displayName, StatusViewData status) { void setMessage(Notification.Type type, String displayName, StatusViewData status) {
@ -281,5 +297,31 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
} }
}); });
} }
void setAvatars(@Nullable String statusAvatarUrl, @Nullable String notificationAvatarUrl) {
Context context = statusAvatar.getContext();
if (statusAvatarUrl == null || statusAvatarUrl.isEmpty()) {
statusAvatar.setImageResource(R.drawable.avatar_default);
} else {
Picasso.with(context)
.load(statusAvatarUrl)
.placeholder(R.drawable.avatar_default)
.error(R.drawable.avatar_error)
.transform(new RoundedTransformation(7, 0))
.into(statusAvatar);
}
if (notificationAvatarUrl == null || notificationAvatarUrl.isEmpty()) {
notificationAvatar.setVisibility(View.GONE);
} else {
notificationAvatar.setVisibility(View.VISIBLE);
Picasso.with(context)
.load(notificationAvatarUrl)
.fit()
.transform(new RoundedTransformation(7, 0))
.into(notificationAvatar);
}
}
} }
} }

View file

@ -32,16 +32,17 @@ import android.widget.TextView;
import android.widget.ToggleButton; import android.widget.ToggleButton;
import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.view.RoundedTransformation;
import com.keylesspalace.tusky.interfaces.StatusActionListener;
import com.keylesspalace.tusky.entity.Status; import com.keylesspalace.tusky.entity.Status;
import com.keylesspalace.tusky.interfaces.StatusActionListener;
import com.keylesspalace.tusky.util.DateUtils; import com.keylesspalace.tusky.util.DateUtils;
import com.keylesspalace.tusky.util.LinkHelper; import com.keylesspalace.tusky.util.LinkHelper;
import com.keylesspalace.tusky.util.ThemeUtils; import com.keylesspalace.tusky.util.ThemeUtils;
import com.keylesspalace.tusky.view.RoundedTransformation;
import com.keylesspalace.tusky.viewdata.StatusViewData; import com.keylesspalace.tusky.viewdata.StatusViewData;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import com.varunest.sparkbutton.SparkButton; import com.varunest.sparkbutton.SparkButton;
import com.varunest.sparkbutton.SparkEventListener; import com.varunest.sparkbutton.SparkEventListener;
import com.varunest.sparkbutton.helpers.Utils;
import java.util.Date; import java.util.Date;
@ -52,6 +53,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
private TextView sinceCreated; private TextView sinceCreated;
private TextView content; private TextView content;
private ImageView avatar; private ImageView avatar;
private ImageView avatarReblog;
private View rebloggedBar; private View rebloggedBar;
private TextView rebloggedByDisplayName; private TextView rebloggedByDisplayName;
private ImageButton replyButton; private ImageButton replyButton;
@ -79,6 +81,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
sinceCreated = (TextView) itemView.findViewById(R.id.status_since_created); sinceCreated = (TextView) itemView.findViewById(R.id.status_since_created);
content = (TextView) itemView.findViewById(R.id.status_content); content = (TextView) itemView.findViewById(R.id.status_content);
avatar = (ImageView) itemView.findViewById(R.id.status_avatar); avatar = (ImageView) itemView.findViewById(R.id.status_avatar);
avatarReblog = (ImageView) itemView.findViewById(R.id.status_avatar_reblog);
rebloggedBar = itemView.findViewById(R.id.status_reblogged_bar); rebloggedBar = itemView.findViewById(R.id.status_reblogged_bar);
rebloggedByDisplayName = (TextView) itemView.findViewById(R.id.status_reblogged); rebloggedByDisplayName = (TextView) itemView.findViewById(R.id.status_reblogged);
replyButton = (ImageButton) itemView.findViewById(R.id.status_reply); replyButton = (ImageButton) itemView.findViewById(R.id.status_reply);
@ -122,17 +125,33 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
LinkHelper.setClickableText(this.content, content, mentions, useCustomTabs, listener); LinkHelper.setClickableText(this.content, content, mentions, useCustomTabs, listener);
} }
private void setAvatar(String url) { private void setAvatar(String url, @Nullable String rebloggedUrl) {
if (url.isEmpty()) {
return;
}
Context context = avatar.getContext(); Context context = avatar.getContext();
Picasso.with(context) boolean hasReblog = rebloggedUrl != null && !rebloggedUrl.isEmpty();
.load(url) int padding = hasReblog ? Utils.dpToPx(context, 12) : 0;
.placeholder(R.drawable.avatar_default) avatar.setPadding(0, 0, padding, padding);
.error(R.drawable.avatar_error)
.transform(new RoundedTransformation(7, 0)) if (url.isEmpty()) {
.into(avatar); avatar.setImageResource(R.drawable.avatar_default);
} else {
Picasso.with(context)
.load(url)
.placeholder(R.drawable.avatar_default)
.error(R.drawable.avatar_error)
.transform(new RoundedTransformation(7, 0))
.into(avatar);
}
if (hasReblog) {
avatarReblog.setVisibility(View.VISIBLE);
Picasso.with(context)
.load(rebloggedUrl)
.fit()
.transform(new RoundedTransformation(7, 0))
.into(avatarReblog);
} else {
avatarReblog.setVisibility(View.GONE);
}
} }
private void setCreatedAt(@Nullable Date createdAt) { private void setCreatedAt(@Nullable Date createdAt) {
@ -460,7 +479,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
setUsername(status.getNickname()); setUsername(status.getNickname());
setCreatedAt(status.getCreatedAt()); setCreatedAt(status.getCreatedAt());
setContent(status.getContent(), status.getMentions(), listener); setContent(status.getContent(), status.getMentions(), listener);
setAvatar(status.getAvatar()); setAvatar(status.getAvatar(), status.getRebloggedAvatar());
setReblogged(status.isReblogged()); setReblogged(status.isReblogged());
setFavourited(status.isFavourited()); setFavourited(status.isFavourited());
String rebloggedByDisplayName = status.getRebloggedByUsername(); String rebloggedByDisplayName = status.getRebloggedByUsername();

View file

@ -32,7 +32,7 @@ public final class ViewDataUtils {
.setIsShowingSensitiveContent(false) .setIsShowingSensitiveContent(false)
.setMentions(visibleStatus.mentions) .setMentions(visibleStatus.mentions)
.setNickname(visibleStatus.account.username) .setNickname(visibleStatus.account.username)
.setRebloggedAvatar(visibleStatus.account.avatar) .setRebloggedAvatar(status.reblog == null ? null : status.account.avatar)
.setSensitive(visibleStatus.sensitive) .setSensitive(visibleStatus.sensitive)
.setSpoilerText(visibleStatus.spoilerText) .setSpoilerText(visibleStatus.spoilerText)
.setRebloggedByUsername(status.reblog == null ? null : status.account.username) .setRebloggedByUsername(status.reblog == null ? null : status.account.username)

View file

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingLeft="16dp" xmlns:tools="http://schemas.android.com/tools"
android:paddingRight="16dp" android:paddingLeft="16dp"
android:id="@+id/status_container"> android:paddingRight="16dp"
android:id="@+id/status_container">
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -50,7 +51,19 @@
android:layout_marginTop="11dp" android:layout_marginTop="11dp"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:layout_marginRight="10dp" android:layout_marginRight="10dp"
android:contentDescription="@string/action_view_profile" /> android:contentDescription="@string/action_view_profile"
tools:src="@drawable/avatar_default"/>
<ImageView
android:id="@+id/status_avatar_reblog"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignBottom="@+id/status_avatar"
android:layout_alignEnd="@id/status_avatar"
android:layout_alignRight="@id/status_avatar"
android:visibility="gone"
tools:src="@color/accent"
tools:visibility="visible"/>
<RelativeLayout <RelativeLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -1,55 +1,84 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--This applies only to favourite and reblog notifications.--> <!--This applies only to favourite and reblog notifications.-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" xmlns:tools="http://schemas.android.com/tools"
android:layout_height="wrap_content" android:id="@+id/notification_container"
android:orientation="vertical" android:layout_width="match_parent"
android:id="@+id/notification_container" android:layout_height="wrap_content"
android:paddingLeft="16dp" android:orientation="vertical"
android:paddingRight="16dp"> android:paddingLeft="16dp"
android:paddingRight="16dp">
<RelativeLayout <RelativeLayout
android:id="@+id/notification_top_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp">
android:id="@+id/notification_top_bar">
<ImageView <ImageView
android:id="@+id/notification_icon"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/notification_icon" android:contentDescription="@null"
android:paddingStart="24dp"
android:paddingLeft="24dp"
android:paddingEnd="10dp" android:paddingEnd="10dp"
android:paddingLeft="24dp"
android:paddingRight="10dp" android:paddingRight="10dp"
app:srcCompat="@drawable/ic_repeat_24dp" android:paddingStart="24dp"
android:contentDescription="@null" /> app:srcCompat="@drawable/ic_repeat_24dp"/>
<TextView <TextView
android:id="@+id/notification_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/notification_text"
android:textColor="?android:textColorSecondary"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:maxLines="1"
android:ellipsize="end"
android:text="Someone favourited your status"
android:layout_toEndOf="@id/notification_icon" android:layout_toEndOf="@id/notification_icon"
android:layout_toRightOf="@id/notification_icon" /> android:layout_toRightOf="@id/notification_icon"
android:ellipsize="end"
android:maxLines="1"
android:text="Someone favourited your status"
android:textColor="?android:textColorSecondary"/>
</RelativeLayout> </RelativeLayout>
<TextView <TextView
android:id="@+id/notification_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/notification_content" android:layout_below="@id/notification_top_bar"
android:paddingStart="58dp"
android:paddingLeft="58dp"
android:paddingEnd="0dp"
android:paddingRight="0dp"
android:paddingBottom="10dp" android:paddingBottom="10dp"
android:text="Example status here" android:paddingEnd="0dp"
android:textColor="?android:textColorTertiary" /> android:paddingLeft="58dp"
android:paddingRight="0dp"
android:paddingStart="58dp"
android:textColor="?android:textColorTertiary"
tools:text="Example status here"/>
</LinearLayout> <ImageView
android:id="@+id/notification_status_avatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignTop="@id/notification_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="11dp"
android:contentDescription="@string/action_view_profile"
android:paddingBottom="12dp"
android:paddingRight="12dp"
android:scaleType="fitCenter"
tools:ignore="RtlHardcoded,RtlSymmetry"
tools:src="@drawable/avatar_default"/>
<ImageView
android:id="@+id/notification_notification_avatar"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignBottom="@+id/notification_status_avatar"
android:layout_alignEnd="@id/notification_status_avatar"
android:layout_alignRight="@id/notification_status_avatar"
android:visibility="gone"
tools:src="@color/accent"
tools:visibility="visible"/>
</RelativeLayout>