Merge branch 'kyori19-AbsoluteTime'

This commit is contained in:
Conny Duck 2018-09-09 21:48:31 +02:00
commit b9ca9a6e97
15 changed files with 153 additions and 61 deletions

View File

@ -61,7 +61,7 @@ public class PreferencesActivity extends BaseActivity
preferences.registerOnSharedPreferenceChangeListener(this); preferences.registerOnSharedPreferenceChangeListener(this);
if(savedInstanceState == null) { if (savedInstanceState == null) {
currentPreferences = R.xml.preferences; currentPreferences = R.xml.preferences;
currentTitle = R.string.action_view_preferences; currentTitle = R.string.action_view_preferences;
} else { } else {
@ -124,6 +124,10 @@ public class PreferencesActivity extends BaseActivity
restartActivitiesOnExit = true; restartActivitiesOnExit = true;
break; break;
} }
case "absoluteTimeView": {
restartActivitiesOnExit = true;
break;
}
case "notificationsEnabled": { case "notificationsEnabled": {
boolean enabled = sharedPreferences.getBoolean("notificationsEnabled", true); boolean enabled = sharedPreferences.getBoolean("notificationsEnabled", true);
if (enabled) { if (enabled) {
@ -145,14 +149,14 @@ public class PreferencesActivity extends BaseActivity
@Override @Override
public void onBackPressed() { public void onBackPressed() {
//if we are not on the top level, show the top level. Else exit the activity //if we are not on the top level, show the top level. Else exit the activity
if(currentPreferences != R.xml.preferences) { if (currentPreferences != R.xml.preferences) {
showFragment(R.xml.preferences, R.string.action_view_preferences); showFragment(R.xml.preferences, R.string.action_view_preferences);
} else { } else {
/* Switching themes won't actually change the theme of activities on the back stack. /* Switching themes won't actually change the theme of activities on the back stack.
* Either the back stack activities need to all be recreated, or do the easier thing, which * Either the back stack activities need to all be recreated, or do the easier thing, which
* is hijack the back button press and use it to launch a new MainActivity and clear the * is hijack the back button press and use it to launch a new MainActivity and clear the
* back stack. */ * back stack. */
if (restartActivitiesOnExit) { if (restartActivitiesOnExit) {
Intent intent = new Intent(this, MainActivity.class); Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

View File

@ -50,9 +50,11 @@ 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 java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale;
public class NotificationsAdapter extends RecyclerView.Adapter { public class NotificationsAdapter extends RecyclerView.Adapter {
private static final int VIEW_TYPE_MENTION = 0; private static final int VIEW_TYPE_MENTION = 0;
@ -64,6 +66,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
private StatusActionListener statusListener; private StatusActionListener statusListener;
private NotificationActionListener notificationActionListener; private NotificationActionListener notificationActionListener;
private boolean mediaPreviewEnabled; private boolean mediaPreviewEnabled;
private boolean useAbsoluteTime;
private BidiFormatter bidiFormatter; private BidiFormatter bidiFormatter;
public NotificationsAdapter(StatusActionListener statusListener, public NotificationsAdapter(StatusActionListener statusListener,
@ -73,6 +76,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
this.statusListener = statusListener; this.statusListener = statusListener;
this.notificationActionListener = notificationActionListener; this.notificationActionListener = notificationActionListener;
mediaPreviewEnabled = true; mediaPreviewEnabled = true;
useAbsoluteTime = false;
bidiFormatter = BidiFormatter.getInstance(); bidiFormatter = BidiFormatter.getInstance();
} }
@ -84,12 +88,12 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
case VIEW_TYPE_MENTION: { case VIEW_TYPE_MENTION: {
View view = LayoutInflater.from(parent.getContext()) View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_status, parent, false); .inflate(R.layout.item_status, parent, false);
return new StatusViewHolder(view); return new StatusViewHolder(view, useAbsoluteTime);
} }
case VIEW_TYPE_STATUS_NOTIFICATION: { case VIEW_TYPE_STATUS_NOTIFICATION: {
View view = LayoutInflater.from(parent.getContext()) View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_status_notification, parent, false); .inflate(R.layout.item_status_notification, parent, false);
return new StatusNotificationViewHolder(view); return new StatusNotificationViewHolder(view, useAbsoluteTime);
} }
case VIEW_TYPE_FOLLOW: { case VIEW_TYPE_FOLLOW: {
View view = LayoutInflater.from(parent.getContext()) View view = LayoutInflater.from(parent.getContext())
@ -130,7 +134,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
StatusNotificationViewHolder holder = (StatusNotificationViewHolder) viewHolder; StatusNotificationViewHolder holder = (StatusNotificationViewHolder) viewHolder;
StatusViewData.Concrete statusViewData = concreteNotificaton.getStatusViewData(); StatusViewData.Concrete statusViewData = concreteNotificaton.getStatusViewData();
if(statusViewData == null) { if (statusViewData == null) {
holder.showNotificationContent(false); holder.showNotificationContent(false);
} else { } else {
holder.showNotificationContent(true); holder.showNotificationContent(true);
@ -228,6 +232,10 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
return mediaPreviewEnabled; return mediaPreviewEnabled;
} }
public void setUseAbsoluteTime(boolean useAbsoluteTime) {
this.useAbsoluteTime = useAbsoluteTime;
}
public interface NotificationActionListener { public interface NotificationActionListener {
void onViewAccount(String id); void onViewAccount(String id);
@ -306,7 +314,11 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
private NotificationActionListener notificationActionListener; private NotificationActionListener notificationActionListener;
private StatusViewData.Concrete statusViewData; private StatusViewData.Concrete statusViewData;
StatusNotificationViewHolder(View itemView) { private boolean useAbsoluteTime;
private SimpleDateFormat shortSdf;
private SimpleDateFormat longSdf;
StatusNotificationViewHolder(View itemView, boolean useAbsoluteTime) {
super(itemView); super(itemView);
message = itemView.findViewById(R.id.notification_top_text); message = itemView.findViewById(R.id.notification_top_text);
statusNameBar = itemView.findViewById(R.id.status_name_bar); statusNameBar = itemView.findViewById(R.id.status_name_bar);
@ -328,6 +340,10 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
message.setOnClickListener(this); message.setOnClickListener(this);
statusContent.setOnClickListener(this); statusContent.setOnClickListener(this);
contentWarningButton.setOnCheckedChangeListener(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) { private void showNotificationContent(boolean show) {
@ -352,26 +368,40 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
username.setText(usernameText); username.setText(usernameText);
} }
private void setCreatedAt(@Nullable Date createdAt) { protected void setCreatedAt(@Nullable Date createdAt) {
// This is the visible timestampInfo. if (useAbsoluteTime) {
String readout; String time;
/* This one is for screen-readers. Frequently, they would mispronounce timestamps like "17m" if (createdAt != null) {
* as 17 meters instead of minutes. */ if (System.currentTimeMillis() - createdAt.getTime() > 86400000L) {
CharSequence readoutAloud; time = longSdf.format(createdAt);
if (createdAt != null) { } else {
long then = createdAt.getTime(); time = shortSdf.format(createdAt);
long now = new Date().getTime(); }
readout = DateUtils.getRelativeTimeSpanString(timestampInfo.getContext(), then, now); } else {
readoutAloud = android.text.format.DateUtils.getRelativeTimeSpanString(then, now, time = "??:??:??";
android.text.format.DateUtils.SECOND_IN_MILLIS, }
android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE); timestampInfo.setText(time);
} else { } else {
// unknown minutes~ // This is the visible timestampInfo.
readout = "?m"; String readout;
readoutAloud = "? minutes"; /* 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) { void setMessage(NotificationViewData.Concrete notificationViewData, LinkListener listener, BidiFormatter bidiFormatter) {
@ -397,7 +427,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
} }
case REBLOG: { case REBLOG: {
icon = ContextCompat.getDrawable(context, R.drawable.ic_repeat_24dp); icon = ContextCompat.getDrawable(context, R.drawable.ic_repeat_24dp);
if(icon != null) { if (icon != null) {
icon.setColorFilter(ContextCompat.getColor(context, icon.setColorFilter(ContextCompat.getColor(context,
R.color.color_accent_dark), PorterDuff.Mode.SRC_ATOP); R.color.color_accent_dark), PorterDuff.Mode.SRC_ATOP);
} }
@ -458,10 +488,12 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
switch (v.getId()) { switch (v.getId()) {
case R.id.notification_container: case R.id.notification_container:
case R.id.notification_content: case R.id.notification_content:
if (notificationActionListener != null) notificationActionListener.onViewStatusForNotificationId(notificationId); if (notificationActionListener != null)
notificationActionListener.onViewStatusForNotificationId(notificationId);
break; break;
case R.id.notification_top_text: case R.id.notification_top_text:
if (notificationActionListener != null) notificationActionListener.onViewAccount(accountId); if (notificationActionListener != null)
notificationActionListener.onViewAccount(accountId);
break; break;
} }
} }

View File

@ -48,12 +48,14 @@ public class SearchResultsAdapter extends RecyclerView.Adapter {
private boolean mediaPreviewsEnabled; private boolean mediaPreviewsEnabled;
private boolean alwaysShowSensitiveMedia; private boolean alwaysShowSensitiveMedia;
private boolean useAbsoluteTime;
private LinkListener linkListener; private LinkListener linkListener;
private StatusActionListener statusListener; private StatusActionListener statusListener;
public SearchResultsAdapter(boolean mediaPreviewsEnabled, boolean alwaysShowSensitiveMedia, public SearchResultsAdapter(boolean mediaPreviewsEnabled, boolean alwaysShowSensitiveMedia,
LinkListener linkListener, StatusActionListener statusListener) { LinkListener linkListener, StatusActionListener statusListener,
boolean useAbsoluteTime) {
this.accountList = Collections.emptyList(); this.accountList = Collections.emptyList();
this.statusList = Collections.emptyList(); this.statusList = Collections.emptyList();
@ -62,6 +64,7 @@ public class SearchResultsAdapter extends RecyclerView.Adapter {
this.mediaPreviewsEnabled = mediaPreviewsEnabled; this.mediaPreviewsEnabled = mediaPreviewsEnabled;
this.alwaysShowSensitiveMedia = alwaysShowSensitiveMedia; this.alwaysShowSensitiveMedia = alwaysShowSensitiveMedia;
this.useAbsoluteTime = useAbsoluteTime;
this.linkListener = linkListener; this.linkListener = linkListener;
this.statusListener = statusListener; this.statusListener = statusListener;
@ -86,7 +89,7 @@ public class SearchResultsAdapter extends RecyclerView.Adapter {
case VIEW_TYPE_STATUS: { case VIEW_TYPE_STATUS: {
View view = LayoutInflater.from(parent.getContext()) View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_status, parent, false); .inflate(R.layout.item_status, parent, false);
return new StatusViewHolder(view); return new StatusViewHolder(view, useAbsoluteTime);
} }
} }
} }

View File

@ -30,8 +30,10 @@ import com.keylesspalace.tusky.viewdata.StatusViewData;
import com.mikepenz.iconics.utils.Utils; import com.mikepenz.iconics.utils.Utils;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale;
import at.connyduck.sparkbutton.SparkButton; import at.connyduck.sparkbutton.SparkButton;
import at.connyduck.sparkbutton.SparkEventListener; import at.connyduck.sparkbutton.SparkEventListener;
@ -64,7 +66,11 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
TextView content; TextView content;
TextView contentWarningDescription; TextView contentWarningDescription;
StatusBaseViewHolder(View itemView) { private boolean useAbsoluteTime;
private SimpleDateFormat shortSdf;
private SimpleDateFormat longSdf;
StatusBaseViewHolder(View itemView, boolean useAbsoluteTime) {
super(itemView); super(itemView);
container = itemView.findViewById(R.id.status_container); container = itemView.findViewById(R.id.status_container);
displayName = itemView.findViewById(R.id.status_display_name); 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); mediaLabel = itemView.findViewById(R.id.status_media_label);
contentWarningDescription = itemView.findViewById(R.id.status_content_warning_description); contentWarningDescription = itemView.findViewById(R.id.status_content_warning_description);
contentWarningButton = itemView.findViewById(R.id.status_content_warning_button); 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); protected abstract int getMediaPreviewHeight(Context context);
@ -126,25 +136,39 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
} }
protected void setCreatedAt(@Nullable Date createdAt) { protected void setCreatedAt(@Nullable Date createdAt) {
// This is the visible timestampInfo. if (useAbsoluteTime) {
String readout; String time;
/* This one is for screen-readers. Frequently, they would mispronounce timestamps like "17m" if (createdAt != null) {
* as 17 meters instead of minutes. */ if (System.currentTimeMillis() - createdAt.getTime() > 86400000L) {
CharSequence readoutAloud; time = longSdf.format(createdAt);
if (createdAt != null) { } else {
long then = createdAt.getTime(); time = shortSdf.format(createdAt);
long now = new Date().getTime(); }
readout = DateUtils.getRelativeTimeSpanString(timestampInfo.getContext(), then, now); } else {
readoutAloud = android.text.format.DateUtils.getRelativeTimeSpanString(then, now, time = "??:??:??";
android.text.format.DateUtils.SECOND_IN_MILLIS, }
android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE); timestampInfo.setText(time);
} else { } else {
// unknown minutes~ // This is the visible timestampInfo.
readout = "?m"; String readout;
readoutAloud = "? minutes"; /* 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) { protected void showContent(boolean show) {
@ -256,7 +280,7 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
final int urlIndex = i; final int urlIndex = i;
previews[i].setOnClickListener(v -> { previews[i].setOnClickListener(v -> {
if(getAdapterPosition() != RecyclerView.NO_POSITION) { if (getAdapterPosition() != RecyclerView.NO_POSITION) {
listener.onViewMedia(getAdapterPosition(), urlIndex, v); listener.onViewMedia(getAdapterPosition(), urlIndex, v);
} }
}); });

View File

@ -41,7 +41,7 @@ class StatusDetailedViewHolder extends StatusBaseViewHolder {
private TextView cardUrl; private TextView cardUrl;
StatusDetailedViewHolder(View view) { StatusDetailedViewHolder(View view) {
super(view); super(view, false);
reblogs = view.findViewById(R.id.status_reblogs); reblogs = view.findViewById(R.id.status_reblogs);
favourites = view.findViewById(R.id.status_favourites); favourites = view.findViewById(R.id.status_favourites);
cardView = view.findViewById(R.id.card_view); cardView = view.findViewById(R.id.card_view);

View File

@ -34,8 +34,8 @@ public class StatusViewHolder extends StatusBaseViewHolder {
private ImageView avatarReblog; private ImageView avatarReblog;
private TextView rebloggedBar; private TextView rebloggedBar;
StatusViewHolder(View itemView) { StatusViewHolder(View itemView, boolean useAbsoluteTime) {
super(itemView); super(itemView, useAbsoluteTime);
avatarReblog = itemView.findViewById(R.id.status_avatar_reblog); avatarReblog = itemView.findViewById(R.id.status_avatar_reblog);
rebloggedBar = itemView.findViewById(R.id.status_reblogged); 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 //workaround because Android < API 21 does not support setting drawableLeft from xml when it is a vector image

View File

@ -36,12 +36,14 @@ public class ThreadAdapter extends RecyclerView.Adapter {
private List<StatusViewData.Concrete> statuses; private List<StatusViewData.Concrete> statuses;
private StatusActionListener statusActionListener; private StatusActionListener statusActionListener;
private boolean mediaPreviewEnabled; private boolean mediaPreviewEnabled;
private boolean useAbsoluteTime;
private int detailedStatusPosition; private int detailedStatusPosition;
public ThreadAdapter(StatusActionListener listener) { public ThreadAdapter(StatusActionListener listener) {
this.statusActionListener = listener; this.statusActionListener = listener;
this.statuses = new ArrayList<>(); this.statuses = new ArrayList<>();
mediaPreviewEnabled = true; mediaPreviewEnabled = true;
useAbsoluteTime = false;
detailedStatusPosition = RecyclerView.NO_POSITION; detailedStatusPosition = RecyclerView.NO_POSITION;
} }
@ -53,7 +55,7 @@ public class ThreadAdapter extends RecyclerView.Adapter {
case VIEW_TYPE_STATUS: { case VIEW_TYPE_STATUS: {
View view = LayoutInflater.from(parent.getContext()) View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_status, parent, false); .inflate(R.layout.item_status, parent, false);
return new StatusViewHolder(view); return new StatusViewHolder(view, useAbsoluteTime);
} }
case VIEW_TYPE_STATUS_DETAILED: { case VIEW_TYPE_STATUS_DETAILED: {
View view = LayoutInflater.from(parent.getContext()) View view = LayoutInflater.from(parent.getContext())
@ -149,6 +151,10 @@ public class ThreadAdapter extends RecyclerView.Adapter {
mediaPreviewEnabled = enabled; mediaPreviewEnabled = enabled;
} }
public void setUseAbsoluteTime(boolean useAbsoluteTime) {
this.useAbsoluteTime = useAbsoluteTime;
}
public void setDetailedStatusPosition(int position) { public void setDetailedStatusPosition(int position) {
if (position != detailedStatusPosition if (position != detailedStatusPosition
&& detailedStatusPosition != RecyclerView.NO_POSITION) { && detailedStatusPosition != RecyclerView.NO_POSITION) {

View File

@ -39,6 +39,7 @@ public final class TimelineAdapter extends RecyclerView.Adapter {
private final AdapterDataSource<StatusViewData> dataSource; private final AdapterDataSource<StatusViewData> dataSource;
private final StatusActionListener statusListener; private final StatusActionListener statusListener;
private boolean mediaPreviewEnabled; private boolean mediaPreviewEnabled;
private boolean useAbsoluteTime;
public TimelineAdapter(AdapterDataSource<StatusViewData> dataSource, public TimelineAdapter(AdapterDataSource<StatusViewData> dataSource,
StatusActionListener statusListener) { StatusActionListener statusListener) {
@ -46,6 +47,7 @@ public final class TimelineAdapter extends RecyclerView.Adapter {
this.dataSource = dataSource; this.dataSource = dataSource;
this.statusListener = statusListener; this.statusListener = statusListener;
mediaPreviewEnabled = true; mediaPreviewEnabled = true;
useAbsoluteTime = false;
} }
@NonNull @NonNull
@ -56,7 +58,7 @@ public final class TimelineAdapter extends RecyclerView.Adapter {
case VIEW_TYPE_STATUS: { case VIEW_TYPE_STATUS: {
View view = LayoutInflater.from(viewGroup.getContext()) View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.item_status, viewGroup, false); .inflate(R.layout.item_status, viewGroup, false);
return new StatusViewHolder(view); return new StatusViewHolder(view, useAbsoluteTime);
} }
case VIEW_TYPE_PLACEHOLDER: { case VIEW_TYPE_PLACEHOLDER: {
View view = LayoutInflater.from(viewGroup.getContext()) View view = LayoutInflater.from(viewGroup.getContext())
@ -97,6 +99,10 @@ public final class TimelineAdapter extends RecyclerView.Adapter {
mediaPreviewEnabled = enabled; mediaPreviewEnabled = enabled;
} }
public void setUseAbsoluteTime(boolean useAbsoluteTime){
this.useAbsoluteTime=useAbsoluteTime;
}
public boolean getMediaPreviewEnabled() { public boolean getMediaPreviewEnabled() {
return mediaPreviewEnabled; return mediaPreviewEnabled;
} }

View File

@ -196,6 +196,8 @@ public class NotificationsFragment extends SFragment implements
alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false); alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false);
boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true); boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true);
adapter.setMediaPreviewEnabled(mediaPreviewEnabled); adapter.setMediaPreviewEnabled(mediaPreviewEnabled);
boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false);
adapter.setUseAbsoluteTime(useAbsoluteTime);
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
notifications.clear(); notifications.clear();

View File

@ -50,6 +50,7 @@ class SearchFragment : SFragment(), StatusActionListener, Injectable {
private var alwaysShowSensitiveMedia = false private var alwaysShowSensitiveMedia = false
private var mediaPreviewEnabled = true private var mediaPreviewEnabled = true
private var useAbsoluteTime = false
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -60,10 +61,11 @@ class SearchFragment : SFragment(), StatusActionListener, Injectable {
val preferences = PreferenceManager.getDefaultSharedPreferences(view.context) val preferences = PreferenceManager.getDefaultSharedPreferences(view.context)
alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false) alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false)
mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true) mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true)
useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false)
searchRecyclerView.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL)) searchRecyclerView.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL))
searchRecyclerView.layoutManager = LinearLayoutManager(view.context) searchRecyclerView.layoutManager = LinearLayoutManager(view.context)
searchAdapter = SearchResultsAdapter(mediaPreviewEnabled, alwaysShowSensitiveMedia, this, this) searchAdapter = SearchResultsAdapter(mediaPreviewEnabled, alwaysShowSensitiveMedia, this, this, useAbsoluteTime)
searchRecyclerView.adapter = searchAdapter searchRecyclerView.adapter = searchAdapter
} }

View File

@ -245,6 +245,8 @@ public class TimelineFragment extends SFragment implements
alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false); alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false);
boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true); boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true);
adapter.setMediaPreviewEnabled(mediaPreviewEnabled); adapter.setMediaPreviewEnabled(mediaPreviewEnabled);
boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false);
adapter.setUseAbsoluteTime(useAbsoluteTime);
boolean filter = preferences.getBoolean("tabFilterHomeReplies", true); boolean filter = preferences.getBoolean("tabFilterHomeReplies", true);
filterRemoveReplies = kind == Kind.HOME && !filter; filterRemoveReplies = kind == Kind.HOME && !filter;
@ -605,7 +607,7 @@ public class TimelineFragment extends SFragment implements
case "mediaPreviewEnabled": { case "mediaPreviewEnabled": {
boolean enabled = sharedPreferences.getBoolean("mediaPreviewEnabled", true); boolean enabled = sharedPreferences.getBoolean("mediaPreviewEnabled", true);
boolean oldMediaPreviewEnabled = adapter.getMediaPreviewEnabled(); boolean oldMediaPreviewEnabled = adapter.getMediaPreviewEnabled();
if(enabled != oldMediaPreviewEnabled) { if (enabled != oldMediaPreviewEnabled) {
adapter.setMediaPreviewEnabled(enabled); adapter.setMediaPreviewEnabled(enabled);
fullyRefresh(); fullyRefresh();
} }
@ -829,7 +831,7 @@ public class TimelineFragment extends SFragment implements
} }
private void onFetchTimelineFailure(Exception exception, FetchEnd fetchEnd, int position) { private void onFetchTimelineFailure(Exception exception, FetchEnd fetchEnd, int position) {
if(isAdded()) { if (isAdded()) {
swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setRefreshing(false);
if (fetchEnd == FetchEnd.MIDDLE && !statuses.get(position).isRight()) { if (fetchEnd == FetchEnd.MIDDLE && !statuses.get(position).isRight()) {
@ -1051,7 +1053,7 @@ public class TimelineFragment extends SFragment implements
private final ListUpdateCallback listUpdateCallback = new ListUpdateCallback() { private final ListUpdateCallback listUpdateCallback = new ListUpdateCallback() {
@Override @Override
public void onInserted(int position, int count) { public void onInserted(int position, int count) {
if(isAdded()) { if (isAdded()) {
adapter.notifyItemRangeInserted(position, count); adapter.notifyItemRangeInserted(position, count);
Context context = getContext(); Context context = getContext();
if (position == 0 && context != null) { if (position == 0 && context != null) {

View File

@ -156,6 +156,8 @@ public final class ViewThreadFragment extends SFragment implements
alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false); alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false);
boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true); boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true);
adapter.setMediaPreviewEnabled(mediaPreviewEnabled); adapter.setMediaPreviewEnabled(mediaPreviewEnabled);
boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false);
adapter.setUseAbsoluteTime(useAbsoluteTime);
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
statuses.clear(); statuses.clear();

View File

@ -277,4 +277,6 @@
<string name="action_set_caption">説明を設定</string> <string name="action_set_caption">説明を設定</string>
<string name="action_remove_media">消去</string> <string name="action_remove_media">消去</string>
<string name="pref_title_absolute_time">絶対時間で表示</string>
</resources> </resources>

View File

@ -347,4 +347,6 @@
<string name="profile_metadata_label_label">Label</string> <string name="profile_metadata_label_label">Label</string>
<string name="profile_metadata_content_label">Content</string> <string name="profile_metadata_content_label">Content</string>
<string name="pref_title_absolute_time">Use absolute time</string>
</resources> </resources>

View File

@ -42,6 +42,11 @@
android:key="alwaysShowSensitiveMedia" android:key="alwaysShowSensitiveMedia"
android:title="@string/pref_title_alway_show_sensitive_media" /> android:title="@string/pref_title_alway_show_sensitive_media" />
<CheckBoxPreference
android:defaultValue="false"
android:key="absoluteTimeView"
android:title="@string/pref_title_absolute_time" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/pref_publishing"> <PreferenceCategory android:title="@string/pref_publishing">