Makes the main status of a thread appear as a more detailed view.
This commit is contained in:
parent
6b3dd30527
commit
309c89eefc
9 changed files with 565 additions and 38 deletions
|
|
@ -51,7 +51,6 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
|
|||
private View container;
|
||||
private TextView displayName;
|
||||
private TextView username;
|
||||
private TextView sinceCreated;
|
||||
private TextView content;
|
||||
private ImageView avatar;
|
||||
private ImageView avatarReblog;
|
||||
|
|
@ -74,12 +73,14 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
|
|||
private TextView contentWarningDescription;
|
||||
private ToggleButton contentWarningButton;
|
||||
|
||||
TextView timestamp;
|
||||
|
||||
StatusViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
container = itemView.findViewById(R.id.status_container);
|
||||
displayName = (TextView) itemView.findViewById(R.id.status_display_name);
|
||||
username = (TextView) itemView.findViewById(R.id.status_username);
|
||||
sinceCreated = (TextView) itemView.findViewById(R.id.status_since_created);
|
||||
timestamp = (TextView) itemView.findViewById(R.id.status_timestamp);
|
||||
content = (TextView) itemView.findViewById(R.id.status_content);
|
||||
avatar = (ImageView) itemView.findViewById(R.id.status_avatar);
|
||||
avatarReblog = (ImageView) itemView.findViewById(R.id.status_avatar_reblog);
|
||||
|
|
@ -147,19 +148,21 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
|
|||
.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);
|
||||
if (avatarReblog != null) {
|
||||
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) {
|
||||
protected void setCreatedAt(@Nullable Date createdAt) {
|
||||
// This is the visible timestamp.
|
||||
String readout;
|
||||
/* This one is for screen-readers. Frequently, they would mispronounce timestamps like "17m"
|
||||
|
|
@ -168,7 +171,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
|
|||
if (createdAt != null) {
|
||||
long then = createdAt.getTime();
|
||||
long now = new Date().getTime();
|
||||
readout = DateUtils.getRelativeTimeSpanString(sinceCreated.getContext(), then, now);
|
||||
readout = DateUtils.getRelativeTimeSpanString(timestamp.getContext(), then, now);
|
||||
readoutAloud = android.text.format.DateUtils.getRelativeTimeSpanString(then, now,
|
||||
android.text.format.DateUtils.SECOND_IN_MILLIS,
|
||||
android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE);
|
||||
|
|
@ -177,11 +180,14 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
|
|||
readout = "?m";
|
||||
readoutAloud = "? minutes";
|
||||
}
|
||||
sinceCreated.setText(readout);
|
||||
sinceCreated.setContentDescription(readoutAloud);
|
||||
timestamp.setText(readout);
|
||||
timestamp.setContentDescription(readoutAloud);
|
||||
}
|
||||
|
||||
private void setRebloggedByDisplayName(String name) {
|
||||
if (rebloggedByDisplayName == null || rebloggedBar == null) {
|
||||
return;
|
||||
}
|
||||
Context context = rebloggedByDisplayName.getContext();
|
||||
String format = context.getString(R.string.status_boosted_format);
|
||||
String boostedText = String.format(format, name);
|
||||
|
|
@ -190,6 +196,9 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
|
|||
}
|
||||
|
||||
private void hideRebloggedByDisplayName() {
|
||||
if (rebloggedBar == null) {
|
||||
return;
|
||||
}
|
||||
rebloggedBar.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
|
@ -529,11 +538,13 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
|
|||
// I think it's not efficient to create new object every time we bind a holder.
|
||||
// More efficient approach would be creating View.OnClickListener during holder creation
|
||||
// and storing StatusActionListener in a variable after binding.
|
||||
rebloggedBar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onOpenReblog(getAdapterPosition());
|
||||
}
|
||||
});
|
||||
if (rebloggedBar != null) {
|
||||
rebloggedBar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onOpenReblog(getAdapterPosition());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,42 +15,83 @@
|
|||
|
||||
package com.keylesspalace.tusky.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.URLSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.util.CustomTabURLSpan;
|
||||
import com.keylesspalace.tusky.viewdata.StatusViewData;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class ThreadAdapter extends RecyclerView.Adapter {
|
||||
private static final int VIEW_TYPE_STATUS = 0;
|
||||
private static final int VIEW_TYPE_STATUS_DETAILED = 1;
|
||||
|
||||
private List<StatusViewData> statuses;
|
||||
private StatusActionListener statusActionListener;
|
||||
private boolean mediaPreviewEnabled;
|
||||
private int detailedStatusPosition;
|
||||
|
||||
public ThreadAdapter(StatusActionListener listener) {
|
||||
this.statusActionListener = listener;
|
||||
this.statuses = new ArrayList<>();
|
||||
mediaPreviewEnabled = true;
|
||||
detailedStatusPosition = RecyclerView.NO_POSITION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_status, parent, false);
|
||||
return new StatusViewHolder(view);
|
||||
switch (viewType) {
|
||||
default:
|
||||
case VIEW_TYPE_STATUS: {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_status, parent, false);
|
||||
return new StatusViewHolder(view);
|
||||
}
|
||||
case VIEW_TYPE_STATUS_DETAILED: {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_status_detailed, parent, false);
|
||||
return new StatusDetailedViewHolder(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
|
||||
StatusViewHolder holder = (StatusViewHolder) viewHolder;
|
||||
StatusViewData status = statuses.get(position);
|
||||
holder.setupWithStatus(status,
|
||||
statusActionListener, mediaPreviewEnabled);
|
||||
if (position == detailedStatusPosition) {
|
||||
StatusDetailedViewHolder holder = (StatusDetailedViewHolder) viewHolder;
|
||||
StatusViewData status = statuses.get(position);
|
||||
holder.setupWithStatus(status, statusActionListener, mediaPreviewEnabled);
|
||||
} else {
|
||||
StatusViewHolder holder = (StatusViewHolder) viewHolder;
|
||||
StatusViewData status = statuses.get(position);
|
||||
holder.setupWithStatus(status, statusActionListener, mediaPreviewEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == detailedStatusPosition) {
|
||||
return VIEW_TYPE_STATUS_DETAILED;
|
||||
} else {
|
||||
return VIEW_TYPE_STATUS;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -72,6 +113,7 @@ public class ThreadAdapter extends RecyclerView.Adapter {
|
|||
public void clearItems() {
|
||||
int oldSize = statuses.size();
|
||||
statuses.clear();
|
||||
detailedStatusPosition = RecyclerView.NO_POSITION;
|
||||
notifyItemRangeRemoved(0, oldSize);
|
||||
}
|
||||
|
||||
|
|
@ -88,15 +130,85 @@ public class ThreadAdapter extends RecyclerView.Adapter {
|
|||
|
||||
public void clear() {
|
||||
statuses.clear();
|
||||
detailedStatusPosition = RecyclerView.NO_POSITION;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setItem(int position, StatusViewData status, boolean notifyAdapter) {
|
||||
statuses.set(position, status);
|
||||
if (notifyAdapter) notifyItemChanged(position);
|
||||
if (notifyAdapter) {
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMediaPreviewEnabled(boolean enabled) {
|
||||
mediaPreviewEnabled = enabled;
|
||||
}
|
||||
|
||||
public void setDetailedStatusPosition(int position) {
|
||||
if (position != detailedStatusPosition
|
||||
&& detailedStatusPosition != RecyclerView.NO_POSITION) {
|
||||
int prior = detailedStatusPosition;
|
||||
detailedStatusPosition = position;
|
||||
notifyItemChanged(prior);
|
||||
} else {
|
||||
detailedStatusPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
private static class StatusDetailedViewHolder extends StatusViewHolder {
|
||||
private TextView reblogs;
|
||||
private TextView favourites;
|
||||
private TextView application;
|
||||
|
||||
StatusDetailedViewHolder(View view) {
|
||||
super(view);
|
||||
reblogs = (TextView) view.findViewById(R.id.status_reblogs);
|
||||
favourites = (TextView) view.findViewById(R.id.status_favourites);
|
||||
application = (TextView) view.findViewById(R.id.status_application);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setCreatedAt(@Nullable Date createdAt) {
|
||||
if (createdAt != null) {
|
||||
DateFormat dateFormat = android.text.format.DateFormat.getMediumDateFormat(
|
||||
timestamp.getContext());
|
||||
timestamp.setText(dateFormat.format(createdAt));
|
||||
} else {
|
||||
timestamp.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
private void setApplication(@Nullable Status.Application app) {
|
||||
if (app == null) {
|
||||
return;
|
||||
}
|
||||
if (app.website != null) {
|
||||
URLSpan span;
|
||||
Context context = application.getContext();
|
||||
boolean useCustomTabs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getBoolean("customTabs", true);
|
||||
if (useCustomTabs) {
|
||||
span = new CustomTabURLSpan(app.website);
|
||||
} else {
|
||||
span = new URLSpan(app.website);
|
||||
}
|
||||
SpannableStringBuilder text = new SpannableStringBuilder(app.name);
|
||||
text.setSpan(span, 0, app.name.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
application.setText(text);
|
||||
application.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
} else {
|
||||
application.setText(app.name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void setupWithStatus(StatusViewData status, final StatusActionListener listener,
|
||||
boolean mediaPreviewEnabled) {
|
||||
super.setupWithStatus(status, listener, mediaPreviewEnabled);
|
||||
reblogs.setText(status.getReblogsCount());
|
||||
favourites.setText(status.getFavouritesCount());
|
||||
setApplication(status.getApplication());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue