Follow notifications now allow you to view the account that followed and follow back from the notification timeline.

This commit is contained in:
Vavassor 2017-02-26 20:14:13 -05:00
parent 9dceb7a226
commit 0a32c58801
5 changed files with 172 additions and 27 deletions

View file

@ -34,13 +34,20 @@ class Notification {
private Type type; private Type type;
private String id; private String id;
private String displayName; private String displayName;
private String username;
private String avatar;
private String accountId;
/** Which of the user's statuses has been mentioned, reblogged, or favourited. */ /** Which of the user's statuses has been mentioned, reblogged, or favourited. */
private Status status; private Status status;
private Notification(Type type, String id, String displayName) { private Notification(Type type, String id, String displayName, String username, String avatar,
String accountId) {
this.type = type; this.type = type;
this.id = id; this.id = id;
this.displayName = displayName; this.displayName = displayName;
this.username = username;
this.avatar = avatar;
this.accountId = accountId;
} }
Type getType() { Type getType() {
@ -55,6 +62,18 @@ class Notification {
return displayName; return displayName;
} }
String getUsername() {
return username;
}
String getAvatar() {
return avatar;
}
String getAccountId() {
return accountId;
}
@Nullable Status getStatus() { @Nullable Status getStatus() {
return status; return status;
} }
@ -81,7 +100,11 @@ class Notification {
if (displayName.isEmpty()) { if (displayName.isEmpty()) {
displayName = account.getString("username"); displayName = account.getString("username");
} }
Notification notification = new Notification(type, id, displayName); String username = account.getString("acct");
String avatar = account.getString("avatar");
String accountId = account.getString("id");
Notification notification = new Notification(type, id, displayName, username, avatar,
accountId);
if (notification.hasStatusType()) { if (notification.hasStatusType()) {
JSONObject statusObject = object.getJSONObject("status"); JSONObject statusObject = object.getJSONObject("status");
Status status = Status.parse(statusObject, false); Status status = Status.parse(statusObject, false);

View file

@ -21,9 +21,12 @@ import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.android.volley.toolbox.NetworkImageView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -36,14 +39,16 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe
private List<Notification> notifications; private List<Notification> notifications;
private StatusActionListener statusListener; private StatusActionListener statusListener;
private FollowListener followListener;
private FooterActionListener footerListener; private FooterActionListener footerListener;
private FooterViewHolder.State footerState; private FooterViewHolder.State footerState;
NotificationsAdapter(StatusActionListener statusListener, NotificationsAdapter(StatusActionListener statusListener, FollowListener followListener,
FooterActionListener footerListener) { FooterActionListener footerListener) {
super(); super();
notifications = new ArrayList<>(); notifications = new ArrayList<>();
this.statusListener = statusListener; this.statusListener = statusListener;
this.followListener = followListener;
this.footerListener = footerListener; this.footerListener = footerListener;
footerState = FooterViewHolder.State.LOADING; footerState = FooterViewHolder.State.LOADING;
} }
@ -96,7 +101,10 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe
} }
case FOLLOW: { case FOLLOW: {
FollowViewHolder holder = (FollowViewHolder) viewHolder; FollowViewHolder holder = (FollowViewHolder) viewHolder;
holder.setMessage(notification.getDisplayName()); holder.setMessage(notification.getDisplayName(), notification.getUsername(),
notification.getAvatar());
holder.setupButtons(followListener, notification.getAccountId(),
notification.getUsername());
break; break;
} }
} }
@ -177,19 +185,59 @@ class NotificationsAdapter extends RecyclerView.Adapter implements AdapterItemRe
footerState = state; footerState = state;
} }
interface FollowListener {
void onViewAccount(String id, String username);
void onFollow(String id);
}
private static class FollowViewHolder extends RecyclerView.ViewHolder { private static class FollowViewHolder extends RecyclerView.ViewHolder {
private TextView message; private TextView message;
private TextView usernameView;
private TextView displayNameView;
private NetworkImageView avatar;
private Button follow;
FollowViewHolder(View itemView) { FollowViewHolder(View itemView) {
super(itemView); super(itemView);
message = (TextView) itemView.findViewById(R.id.notification_text); message = (TextView) itemView.findViewById(R.id.notification_text);
usernameView = (TextView) itemView.findViewById(R.id.notification_username);
displayNameView = (TextView) itemView.findViewById(R.id.notification_display_name);
avatar = (NetworkImageView) itemView.findViewById(R.id.notification_avatar);
avatar.setDefaultImageResId(R.drawable.avatar_default);
avatar.setErrorImageResId(R.drawable.avatar_error);
follow = (Button) itemView.findViewById(R.id.notification_follow_button);
} }
void setMessage(String displayName) { void setMessage(String displayName, String username, String avatarUrl) {
Context context = message.getContext(); Context context = message.getContext();
String format = context.getString(R.string.notification_follow_format); String format = context.getString(R.string.notification_follow_format);
String wholeMessage = String.format(format, displayName); String wholeMessage = String.format(format, displayName);
message.setText(wholeMessage); message.setText(wholeMessage);
format = context.getString(R.string.status_username_format);
String wholeUsername = String.format(format, username);
usernameView.setText(wholeUsername);
displayNameView.setText(displayName);
avatar.setImageUrl(avatarUrl, VolleySingleton.getInstance(context).getImageLoader());
}
void setupButtons(final FollowListener listener, final String accountId,
final String username) {
avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onViewAccount(accountId, username);
}
});
follow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onFollow(accountId);
}
});
} }
} }

View file

@ -41,7 +41,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
public class NotificationsFragment extends SFragment implements public class NotificationsFragment extends SFragment implements
SwipeRefreshLayout.OnRefreshListener, StatusActionListener, FooterActionListener { SwipeRefreshLayout.OnRefreshListener, StatusActionListener, FooterActionListener,
NotificationsAdapter.FollowListener {
private static final String TAG = "Notifications"; // logging tag and Volley request tag private static final String TAG = "Notifications"; // logging tag and Volley request tag
private SwipeRefreshLayout swipeRefreshLayout; private SwipeRefreshLayout swipeRefreshLayout;
@ -98,7 +99,7 @@ public class NotificationsFragment extends SFragment implements
} }
}; };
recyclerView.addOnScrollListener(scrollListener); recyclerView.addOnScrollListener(scrollListener);
adapter = new NotificationsAdapter(this, this); adapter = new NotificationsAdapter(this, this, this);
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
TabLayout layout = (TabLayout) getActivity().findViewById(R.id.tab_layout); TabLayout layout = (TabLayout) getActivity().findViewById(R.id.tab_layout);
@ -266,4 +267,8 @@ public class NotificationsFragment extends SFragment implements
String username = status.getUsername(); String username = status.getUsername();
super.viewAccount(id, username); super.viewAccount(id, username);
} }
public void onFollow(String id) {
super.follow(id);
}
} }

View file

@ -161,7 +161,7 @@ public class SFragment extends Fragment {
}, null); }, null);
} }
private void follow(String id) { protected void follow(String id) {
String endpoint = String.format(getString(R.string.endpoint_follow), id); String endpoint = String.format(getString(R.string.endpoint_follow), id);
postRequest(endpoint); postRequest(endpoint);
} }

View file

@ -1,25 +1,94 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <!--
* This is the for follow notifications, the layout for the follows/following listings on account
* pages are instead in item_account.xml.
-->
<LinearLayout 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:orientation="vertical">
<ImageView <RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/follow_icon"
app:srcCompat="@drawable/ic_followed"
android:paddingTop="@dimen/notification_icon_vertical_padding"
android:paddingBottom="@dimen/notification_icon_vertical_padding"
android:paddingRight="@dimen/status_avatar_padding"
android:paddingLeft="@dimen/follow_icon_left_padding"
android:tint="?attr/notification_icon_tint" />
<TextView
android:id="@+id/notification_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:layout_centerVertical="true"
android:layout_toRightOf="@id/follow_icon" />
</RelativeLayout> <ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/follow_icon"
app:srcCompat="@drawable/ic_followed"
android:paddingTop="@dimen/notification_icon_vertical_padding"
android:paddingBottom="@dimen/notification_icon_vertical_padding"
android:paddingRight="@dimen/status_avatar_padding"
android:paddingLeft="@dimen/follow_icon_left_padding"
android:tint="?attr/notification_icon_tint" />
<TextView
android:id="@+id/notification_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/follow_icon" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.android.volley.toolbox.NetworkImageView
android:layout_width="64dp"
android:layout_height="64dp"
android:id="@+id/notification_avatar"
android:scaleType="fitCenter"
android:padding="@dimen/status_avatar_padding"
android:layout_alignParentLeft="true" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="64dp"
android:orientation="vertical"
android:layout_toRightOf="@id/notification_avatar">
<Space
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/notification_display_name"
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Small"
android:textStyle="normal|bold" />
<Space
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/notification_username"
android:textColor="?attr/status_text_color_secondary" />
<Space
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/notification_follow_button"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="@string/action_follow" />
</RelativeLayout>
</LinearLayout>