Merge branch 'AbsoluteTime' of https://github.com/kyori19/Tusky into kyori19-AbsoluteTime
# Conflicts: # app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java
This commit is contained in:
commit
51d231834c
15 changed files with 153 additions and 61 deletions
|
|
@ -50,9 +50,11 @@ import com.keylesspalace.tusky.viewdata.NotificationViewData;
|
|||
import com.keylesspalace.tusky.viewdata.StatusViewData;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class NotificationsAdapter extends RecyclerView.Adapter {
|
||||
private static final int VIEW_TYPE_MENTION = 0;
|
||||
|
|
@ -64,6 +66,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
|||
private StatusActionListener statusListener;
|
||||
private NotificationActionListener notificationActionListener;
|
||||
private boolean mediaPreviewEnabled;
|
||||
private boolean useAbsoluteTime;
|
||||
private BidiFormatter bidiFormatter;
|
||||
|
||||
public NotificationsAdapter(StatusActionListener statusListener,
|
||||
|
|
@ -73,6 +76,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
|||
this.statusListener = statusListener;
|
||||
this.notificationActionListener = notificationActionListener;
|
||||
mediaPreviewEnabled = true;
|
||||
useAbsoluteTime = false;
|
||||
bidiFormatter = BidiFormatter.getInstance();
|
||||
}
|
||||
|
||||
|
|
@ -84,12 +88,12 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
|||
case VIEW_TYPE_MENTION: {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_status, parent, false);
|
||||
return new StatusViewHolder(view);
|
||||
return new StatusViewHolder(view, useAbsoluteTime);
|
||||
}
|
||||
case VIEW_TYPE_STATUS_NOTIFICATION: {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_status_notification, parent, false);
|
||||
return new StatusNotificationViewHolder(view);
|
||||
return new StatusNotificationViewHolder(view, useAbsoluteTime);
|
||||
}
|
||||
case VIEW_TYPE_FOLLOW: {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
|
|
@ -130,7 +134,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
|||
StatusNotificationViewHolder holder = (StatusNotificationViewHolder) viewHolder;
|
||||
StatusViewData.Concrete statusViewData = concreteNotificaton.getStatusViewData();
|
||||
|
||||
if(statusViewData == null) {
|
||||
if (statusViewData == null) {
|
||||
holder.showNotificationContent(false);
|
||||
} else {
|
||||
holder.showNotificationContent(true);
|
||||
|
|
@ -228,6 +232,10 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
|||
return mediaPreviewEnabled;
|
||||
}
|
||||
|
||||
public void setUseAbsoluteTime(boolean useAbsoluteTime) {
|
||||
this.useAbsoluteTime = useAbsoluteTime;
|
||||
}
|
||||
|
||||
public interface NotificationActionListener {
|
||||
void onViewAccount(String id);
|
||||
|
||||
|
|
@ -306,7 +314,11 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
|||
private NotificationActionListener notificationActionListener;
|
||||
private StatusViewData.Concrete statusViewData;
|
||||
|
||||
StatusNotificationViewHolder(View itemView) {
|
||||
private boolean useAbsoluteTime;
|
||||
private SimpleDateFormat shortSdf;
|
||||
private SimpleDateFormat longSdf;
|
||||
|
||||
StatusNotificationViewHolder(View itemView, boolean useAbsoluteTime) {
|
||||
super(itemView);
|
||||
message = itemView.findViewById(R.id.notification_top_text);
|
||||
statusNameBar = itemView.findViewById(R.id.status_name_bar);
|
||||
|
|
@ -328,6 +340,10 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
|||
message.setOnClickListener(this);
|
||||
statusContent.setOnClickListener(this);
|
||||
contentWarningButton.setOnCheckedChangeListener(this);
|
||||
|
||||
this.useAbsoluteTime = useAbsoluteTime;
|
||||
shortSdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
|
||||
longSdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault());
|
||||
}
|
||||
|
||||
private void showNotificationContent(boolean show) {
|
||||
|
|
@ -352,26 +368,40 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
|||
username.setText(usernameText);
|
||||
}
|
||||
|
||||
private void setCreatedAt(@Nullable Date createdAt) {
|
||||
// This is the visible timestampInfo.
|
||||
String readout;
|
||||
/* This one is for screen-readers. Frequently, they would mispronounce timestamps like "17m"
|
||||
* as 17 meters instead of minutes. */
|
||||
CharSequence readoutAloud;
|
||||
if (createdAt != null) {
|
||||
long then = createdAt.getTime();
|
||||
long now = new Date().getTime();
|
||||
readout = DateUtils.getRelativeTimeSpanString(timestampInfo.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);
|
||||
protected void setCreatedAt(@Nullable Date createdAt) {
|
||||
if (useAbsoluteTime) {
|
||||
String time;
|
||||
if (createdAt != null) {
|
||||
if (System.currentTimeMillis() - createdAt.getTime() > 86400000L) {
|
||||
time = longSdf.format(createdAt);
|
||||
} else {
|
||||
time = shortSdf.format(createdAt);
|
||||
}
|
||||
} else {
|
||||
time = "??:??:??";
|
||||
}
|
||||
timestampInfo.setText(time);
|
||||
} else {
|
||||
// unknown minutes~
|
||||
readout = "?m";
|
||||
readoutAloud = "? minutes";
|
||||
// This is the visible timestampInfo.
|
||||
String readout;
|
||||
/* This one is for screen-readers. Frequently, they would mispronounce timestamps like "17m"
|
||||
* as 17 meters instead of minutes. */
|
||||
CharSequence readoutAloud;
|
||||
if (createdAt != null) {
|
||||
long then = createdAt.getTime();
|
||||
long now = new Date().getTime();
|
||||
readout = DateUtils.getRelativeTimeSpanString(timestampInfo.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);
|
||||
} else {
|
||||
// unknown minutes~
|
||||
readout = "?m";
|
||||
readoutAloud = "? minutes";
|
||||
}
|
||||
timestampInfo.setText(readout);
|
||||
timestampInfo.setContentDescription(readoutAloud);
|
||||
}
|
||||
timestampInfo.setText(readout);
|
||||
timestampInfo.setContentDescription(readoutAloud);
|
||||
}
|
||||
|
||||
void setMessage(NotificationViewData.Concrete notificationViewData, LinkListener listener, BidiFormatter bidiFormatter) {
|
||||
|
|
@ -397,7 +427,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
|||
}
|
||||
case REBLOG: {
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_repeat_24dp);
|
||||
if(icon != null) {
|
||||
if (icon != null) {
|
||||
icon.setColorFilter(ContextCompat.getColor(context,
|
||||
R.color.color_accent_dark), PorterDuff.Mode.SRC_ATOP);
|
||||
}
|
||||
|
|
@ -458,10 +488,12 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
|||
switch (v.getId()) {
|
||||
case R.id.notification_container:
|
||||
case R.id.notification_content:
|
||||
if (notificationActionListener != null) notificationActionListener.onViewStatusForNotificationId(notificationId);
|
||||
if (notificationActionListener != null)
|
||||
notificationActionListener.onViewStatusForNotificationId(notificationId);
|
||||
break;
|
||||
case R.id.notification_top_text:
|
||||
if (notificationActionListener != null) notificationActionListener.onViewAccount(accountId);
|
||||
if (notificationActionListener != null)
|
||||
notificationActionListener.onViewAccount(accountId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,12 +48,14 @@ public class SearchResultsAdapter extends RecyclerView.Adapter {
|
|||
|
||||
private boolean mediaPreviewsEnabled;
|
||||
private boolean alwaysShowSensitiveMedia;
|
||||
private boolean useAbsoluteTime;
|
||||
|
||||
private LinkListener linkListener;
|
||||
private StatusActionListener statusListener;
|
||||
|
||||
public SearchResultsAdapter(boolean mediaPreviewsEnabled, boolean alwaysShowSensitiveMedia,
|
||||
LinkListener linkListener, StatusActionListener statusListener) {
|
||||
LinkListener linkListener, StatusActionListener statusListener,
|
||||
boolean useAbsoluteTime) {
|
||||
|
||||
this.accountList = Collections.emptyList();
|
||||
this.statusList = Collections.emptyList();
|
||||
|
|
@ -62,6 +64,7 @@ public class SearchResultsAdapter extends RecyclerView.Adapter {
|
|||
|
||||
this.mediaPreviewsEnabled = mediaPreviewsEnabled;
|
||||
this.alwaysShowSensitiveMedia = alwaysShowSensitiveMedia;
|
||||
this.useAbsoluteTime = useAbsoluteTime;
|
||||
|
||||
this.linkListener = linkListener;
|
||||
this.statusListener = statusListener;
|
||||
|
|
@ -86,7 +89,7 @@ public class SearchResultsAdapter extends RecyclerView.Adapter {
|
|||
case VIEW_TYPE_STATUS: {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_status, parent, false);
|
||||
return new StatusViewHolder(view);
|
||||
return new StatusViewHolder(view, useAbsoluteTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,10 @@ import com.keylesspalace.tusky.viewdata.StatusViewData;
|
|||
import com.mikepenz.iconics.utils.Utils;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import at.connyduck.sparkbutton.SparkButton;
|
||||
import at.connyduck.sparkbutton.SparkEventListener;
|
||||
|
|
@ -64,7 +66,11 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
|||
TextView content;
|
||||
TextView contentWarningDescription;
|
||||
|
||||
StatusBaseViewHolder(View itemView) {
|
||||
private boolean useAbsoluteTime;
|
||||
private SimpleDateFormat shortSdf;
|
||||
private SimpleDateFormat longSdf;
|
||||
|
||||
StatusBaseViewHolder(View itemView, boolean useAbsoluteTime) {
|
||||
super(itemView);
|
||||
container = itemView.findViewById(R.id.status_container);
|
||||
displayName = itemView.findViewById(R.id.status_display_name);
|
||||
|
|
@ -91,6 +97,10 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
|||
mediaLabel = itemView.findViewById(R.id.status_media_label);
|
||||
contentWarningDescription = itemView.findViewById(R.id.status_content_warning_description);
|
||||
contentWarningButton = itemView.findViewById(R.id.status_content_warning_button);
|
||||
|
||||
this.useAbsoluteTime = useAbsoluteTime;
|
||||
shortSdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
|
||||
longSdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault());
|
||||
}
|
||||
|
||||
protected abstract int getMediaPreviewHeight(Context context);
|
||||
|
|
@ -126,25 +136,39 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
|||
}
|
||||
|
||||
protected void setCreatedAt(@Nullable Date createdAt) {
|
||||
// This is the visible timestampInfo.
|
||||
String readout;
|
||||
/* This one is for screen-readers. Frequently, they would mispronounce timestamps like "17m"
|
||||
* as 17 meters instead of minutes. */
|
||||
CharSequence readoutAloud;
|
||||
if (createdAt != null) {
|
||||
long then = createdAt.getTime();
|
||||
long now = new Date().getTime();
|
||||
readout = DateUtils.getRelativeTimeSpanString(timestampInfo.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);
|
||||
if (useAbsoluteTime) {
|
||||
String time;
|
||||
if (createdAt != null) {
|
||||
if (System.currentTimeMillis() - createdAt.getTime() > 86400000L) {
|
||||
time = longSdf.format(createdAt);
|
||||
} else {
|
||||
time = shortSdf.format(createdAt);
|
||||
}
|
||||
} else {
|
||||
time = "??:??:??";
|
||||
}
|
||||
timestampInfo.setText(time);
|
||||
} else {
|
||||
// unknown minutes~
|
||||
readout = "?m";
|
||||
readoutAloud = "? minutes";
|
||||
// This is the visible timestampInfo.
|
||||
String readout;
|
||||
/* This one is for screen-readers. Frequently, they would mispronounce timestamps like "17m"
|
||||
* as 17 meters instead of minutes. */
|
||||
CharSequence readoutAloud;
|
||||
if (createdAt != null) {
|
||||
long then = createdAt.getTime();
|
||||
long now = new Date().getTime();
|
||||
readout = DateUtils.getRelativeTimeSpanString(timestampInfo.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);
|
||||
} else {
|
||||
// unknown minutes~
|
||||
readout = "?m";
|
||||
readoutAloud = "? minutes";
|
||||
}
|
||||
timestampInfo.setText(readout);
|
||||
timestampInfo.setContentDescription(readoutAloud);
|
||||
}
|
||||
timestampInfo.setText(readout);
|
||||
timestampInfo.setContentDescription(readoutAloud);
|
||||
}
|
||||
|
||||
protected void showContent(boolean show) {
|
||||
|
|
@ -256,7 +280,7 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
|||
|
||||
final int urlIndex = i;
|
||||
previews[i].setOnClickListener(v -> {
|
||||
if(getAdapterPosition() != RecyclerView.NO_POSITION) {
|
||||
if (getAdapterPosition() != RecyclerView.NO_POSITION) {
|
||||
listener.onViewMedia(getAdapterPosition(), urlIndex, v);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class StatusDetailedViewHolder extends StatusBaseViewHolder {
|
|||
private TextView cardUrl;
|
||||
|
||||
StatusDetailedViewHolder(View view) {
|
||||
super(view);
|
||||
super(view, false);
|
||||
reblogs = view.findViewById(R.id.status_reblogs);
|
||||
favourites = view.findViewById(R.id.status_favourites);
|
||||
cardView = view.findViewById(R.id.card_view);
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ public class StatusViewHolder extends StatusBaseViewHolder {
|
|||
private ImageView avatarReblog;
|
||||
private TextView rebloggedBar;
|
||||
|
||||
StatusViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
StatusViewHolder(View itemView, boolean useAbsoluteTime) {
|
||||
super(itemView, useAbsoluteTime);
|
||||
avatarReblog = itemView.findViewById(R.id.status_avatar_reblog);
|
||||
rebloggedBar = itemView.findViewById(R.id.status_reblogged);
|
||||
//workaround because Android < API 21 does not support setting drawableLeft from xml when it is a vector image
|
||||
|
|
|
|||
|
|
@ -36,12 +36,14 @@ public class ThreadAdapter extends RecyclerView.Adapter {
|
|||
private List<StatusViewData.Concrete> statuses;
|
||||
private StatusActionListener statusActionListener;
|
||||
private boolean mediaPreviewEnabled;
|
||||
private boolean useAbsoluteTime;
|
||||
private int detailedStatusPosition;
|
||||
|
||||
public ThreadAdapter(StatusActionListener listener) {
|
||||
this.statusActionListener = listener;
|
||||
this.statuses = new ArrayList<>();
|
||||
mediaPreviewEnabled = true;
|
||||
useAbsoluteTime = false;
|
||||
detailedStatusPosition = RecyclerView.NO_POSITION;
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +55,7 @@ public class ThreadAdapter extends RecyclerView.Adapter {
|
|||
case VIEW_TYPE_STATUS: {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_status, parent, false);
|
||||
return new StatusViewHolder(view);
|
||||
return new StatusViewHolder(view, useAbsoluteTime);
|
||||
}
|
||||
case VIEW_TYPE_STATUS_DETAILED: {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
|
|
@ -149,6 +151,10 @@ public class ThreadAdapter extends RecyclerView.Adapter {
|
|||
mediaPreviewEnabled = enabled;
|
||||
}
|
||||
|
||||
public void setUseAbsoluteTime(boolean useAbsoluteTime) {
|
||||
this.useAbsoluteTime = useAbsoluteTime;
|
||||
}
|
||||
|
||||
public void setDetailedStatusPosition(int position) {
|
||||
if (position != detailedStatusPosition
|
||||
&& detailedStatusPosition != RecyclerView.NO_POSITION) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ public final class TimelineAdapter extends RecyclerView.Adapter {
|
|||
private final AdapterDataSource<StatusViewData> dataSource;
|
||||
private final StatusActionListener statusListener;
|
||||
private boolean mediaPreviewEnabled;
|
||||
private boolean useAbsoluteTime;
|
||||
|
||||
public TimelineAdapter(AdapterDataSource<StatusViewData> dataSource,
|
||||
StatusActionListener statusListener) {
|
||||
|
|
@ -46,6 +47,7 @@ public final class TimelineAdapter extends RecyclerView.Adapter {
|
|||
this.dataSource = dataSource;
|
||||
this.statusListener = statusListener;
|
||||
mediaPreviewEnabled = true;
|
||||
useAbsoluteTime = false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -56,7 +58,7 @@ public final class TimelineAdapter extends RecyclerView.Adapter {
|
|||
case VIEW_TYPE_STATUS: {
|
||||
View view = LayoutInflater.from(viewGroup.getContext())
|
||||
.inflate(R.layout.item_status, viewGroup, false);
|
||||
return new StatusViewHolder(view);
|
||||
return new StatusViewHolder(view, useAbsoluteTime);
|
||||
}
|
||||
case VIEW_TYPE_PLACEHOLDER: {
|
||||
View view = LayoutInflater.from(viewGroup.getContext())
|
||||
|
|
@ -97,6 +99,10 @@ public final class TimelineAdapter extends RecyclerView.Adapter {
|
|||
mediaPreviewEnabled = enabled;
|
||||
}
|
||||
|
||||
public void setUseAbsoluteTime(boolean useAbsoluteTime){
|
||||
this.useAbsoluteTime=useAbsoluteTime;
|
||||
}
|
||||
|
||||
public boolean getMediaPreviewEnabled() {
|
||||
return mediaPreviewEnabled;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue