From ca3a5791e3f2454b9a94625889881c978adfb502 Mon Sep 17 00:00:00 2001 From: kyori Date: Thu, 16 Aug 2018 22:51:23 +0900 Subject: [PATCH 1/9] Show absolute time --- .../tusky/PreferencesActivity.java | 22 +++++--- .../tusky/adapter/StatusBaseViewHolder.java | 55 +++++++++++++------ app/src/main/res/values-ja/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/preferences.xml | 5 ++ 5 files changed, 60 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/PreferencesActivity.java b/app/src/main/java/com/keylesspalace/tusky/PreferencesActivity.java index 67131089..36a4cd32 100644 --- a/app/src/main/java/com/keylesspalace/tusky/PreferencesActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/PreferencesActivity.java @@ -34,8 +34,10 @@ public class PreferencesActivity extends BaseActivity implements SharedPreferences.OnSharedPreferenceChangeListener { private boolean restartActivitiesOnExit; - private @XmlRes int currentPreferences; - private @StringRes int currentTitle; + private @XmlRes + int currentPreferences; + private @StringRes + int currentTitle; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -61,7 +63,7 @@ public class PreferencesActivity extends BaseActivity preferences.registerOnSharedPreferenceChangeListener(this); - if(savedInstanceState == null) { + if (savedInstanceState == null) { currentPreferences = R.xml.preferences; currentTitle = R.string.action_view_preferences; } else { @@ -124,6 +126,10 @@ public class PreferencesActivity extends BaseActivity restartActivitiesOnExit = true; break; } + case "absoluteTimeView": { + restartActivitiesOnExit = true; + break; + } case "notificationsEnabled": { boolean enabled = sharedPreferences.getBoolean("notificationsEnabled", true); if (enabled) { @@ -145,14 +151,14 @@ public class PreferencesActivity extends BaseActivity @Override public void onBackPressed() { //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); } else { - /* 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 - * is hijack the back button press and use it to launch a new MainActivity and clear 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 + * is hijack the back button press and use it to launch a new MainActivity and clear the + * back stack. */ if (restartActivitiesOnExit) { Intent intent = new Intent(this, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index 4a920c07..a1e2bce0 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -1,7 +1,9 @@ package com.keylesspalace.tusky.adapter; import android.content.Context; +import android.content.SharedPreferences; import android.graphics.drawable.Drawable; +import android.preference.PreferenceManager; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -30,8 +32,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; @@ -126,25 +130,40 @@ 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); + SharedPreferences defPrefs = PreferenceManager.getDefaultSharedPreferences(timestampInfo.getContext()); + if (defPrefs.getBoolean("absoluteTimeView", true)) { + String time = "ERROR!"; + if (createdAt != null) { + SimpleDateFormat sdf; + if (new Date().getTime() - createdAt.getTime() > 86400000L) { + sdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault()); + } else { + sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); + } + time = sdf.format(createdAt); + 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 +275,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); } }); diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 5032f052..f3e3a2f6 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -277,4 +277,6 @@ 説明を設定 消去 + 絶対時間で表示 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1a1ff7d0..1cac71b2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -347,4 +347,6 @@ Label Content + Use absolute time + diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 1dd472b8..c9b125d6 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -42,6 +42,11 @@ android:key="alwaysShowSensitiveMedia" android:title="@string/pref_title_alway_show_sensitive_media" /> + + From 1d657a65a7760eb9efc859fbd21290400e2044ba Mon Sep 17 00:00:00 2001 From: kyori Date: Thu, 16 Aug 2018 23:10:21 +0900 Subject: [PATCH 2/9] Show absolute time in Notifications tab --- .../tusky/adapter/NotificationsAdapter.java | 55 +++++++++++++------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java index 136805fa..a014c58f 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java @@ -16,10 +16,12 @@ package com.keylesspalace.tusky.adapter; import android.content.Context; +import android.content.SharedPreferences; import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; @@ -50,9 +52,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; @@ -365,26 +369,41 @@ 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) { + SharedPreferences defPrefs = PreferenceManager.getDefaultSharedPreferences(timestampInfo.getContext()); + if (defPrefs.getBoolean("absoluteTimeView", true)) { + String time = "ERROR!"; + if (createdAt != null) { + SimpleDateFormat sdf; + if (new Date().getTime() - createdAt.getTime() > 86400000L) { + sdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault()); + } else { + sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); + } + time = sdf.format(createdAt); + 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) { From e83dd16942e7fab747e01569fc6631f27302b7a9 Mon Sep 17 00:00:00 2001 From: kyori Date: Fri, 17 Aug 2018 10:19:50 +0900 Subject: [PATCH 3/9] Do not use absolute time by default. --- app/src/main/res/xml/preferences.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index c9b125d6..d53d0f1a 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -43,7 +43,7 @@ android:title="@string/pref_title_alway_show_sensitive_media" /> From 6d1ec789840a247032fa80317c14e0808d92196e Mon Sep 17 00:00:00 2001 From: kyori Date: Fri, 17 Aug 2018 10:21:55 +0900 Subject: [PATCH 4/9] Annotate on same line. --- .../java/com/keylesspalace/tusky/PreferencesActivity.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/PreferencesActivity.java b/app/src/main/java/com/keylesspalace/tusky/PreferencesActivity.java index 36a4cd32..c4f002ef 100644 --- a/app/src/main/java/com/keylesspalace/tusky/PreferencesActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/PreferencesActivity.java @@ -34,10 +34,8 @@ public class PreferencesActivity extends BaseActivity implements SharedPreferences.OnSharedPreferenceChangeListener { private boolean restartActivitiesOnExit; - private @XmlRes - int currentPreferences; - private @StringRes - int currentTitle; + private @XmlRes int currentPreferences; + private @StringRes int currentTitle; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { From 219eafe6fce2f55569ec6dad16d0c5db8f876021 Mon Sep 17 00:00:00 2001 From: kyori Date: Fri, 17 Aug 2018 11:53:38 +0900 Subject: [PATCH 5/9] Prevent query SharedPreference in adapters. --- .../tusky/adapter/NotificationsAdapter.java | 31 ++++++++++++------- .../tusky/adapter/SearchResultsAdapter.java | 7 +++-- .../tusky/adapter/StatusBaseViewHolder.java | 11 ++++--- .../adapter/StatusDetailedViewHolder.java | 2 +- .../tusky/adapter/StatusViewHolder.java | 4 +-- .../tusky/adapter/ThreadAdapter.java | 8 ++++- .../tusky/adapter/TimelineAdapter.java | 8 ++++- .../tusky/fragment/NotificationsFragment.java | 2 ++ .../tusky/fragment/SearchFragment.kt | 4 ++- .../tusky/fragment/TimelineFragment.java | 8 +++-- .../tusky/fragment/ViewThreadFragment.java | 2 ++ 11 files changed, 60 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java index a014c58f..ee69a5e4 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java @@ -16,12 +16,10 @@ package com.keylesspalace.tusky.adapter; import android.content.Context; -import android.content.SharedPreferences; import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.Typeface; import android.graphics.drawable.Drawable; -import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; @@ -70,6 +68,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter { private NotificationActionListener notificationActionListener; private FooterViewHolder.State footerState; private boolean mediaPreviewEnabled; + private boolean useAbsoluteTime; private BidiFormatter bidiFormatter; public NotificationsAdapter(StatusActionListener statusListener, @@ -80,6 +79,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter { this.notificationActionListener = notificationActionListener; footerState = FooterViewHolder.State.END; mediaPreviewEnabled = true; + useAbsoluteTime = false; bidiFormatter = BidiFormatter.getInstance(); } @@ -91,7 +91,7 @@ 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_FOOTER: { View view = LayoutInflater.from(parent.getContext()) @@ -101,7 +101,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter { 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()) @@ -142,7 +142,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); @@ -245,6 +245,10 @@ public class NotificationsAdapter extends RecyclerView.Adapter { mediaPreviewEnabled = enabled; } + public void setUseAbsoluteTime(boolean useAbsoluteTime) { + this.useAbsoluteTime = useAbsoluteTime; + } + public interface NotificationActionListener { void onViewAccount(String id); @@ -323,7 +327,9 @@ public class NotificationsAdapter extends RecyclerView.Adapter { private NotificationActionListener notificationActionListener; private StatusViewData.Concrete statusViewData; - StatusNotificationViewHolder(View itemView) { + private boolean useAbsoluteTime; + + StatusNotificationViewHolder(View itemView, boolean useAbsoluteTime) { super(itemView); message = itemView.findViewById(R.id.notification_top_text); statusNameBar = itemView.findViewById(R.id.status_name_bar); @@ -345,6 +351,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter { message.setOnClickListener(this); statusContent.setOnClickListener(this); contentWarningButton.setOnCheckedChangeListener(this); + + this.useAbsoluteTime = useAbsoluteTime; } private void showNotificationContent(boolean show) { @@ -370,8 +378,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter { } protected void setCreatedAt(@Nullable Date createdAt) { - SharedPreferences defPrefs = PreferenceManager.getDefaultSharedPreferences(timestampInfo.getContext()); - if (defPrefs.getBoolean("absoluteTimeView", true)) { + if (useAbsoluteTime) { String time = "ERROR!"; if (createdAt != null) { SimpleDateFormat sdf; @@ -429,7 +436,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); } @@ -490,10 +497,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; } } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/SearchResultsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/SearchResultsAdapter.java index 24aea0be..662e64f4 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/SearchResultsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/SearchResultsAdapter.java @@ -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); } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index a1e2bce0..b9191144 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -1,9 +1,7 @@ package com.keylesspalace.tusky.adapter; import android.content.Context; -import android.content.SharedPreferences; import android.graphics.drawable.Drawable; -import android.preference.PreferenceManager; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -68,7 +66,9 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { TextView content; TextView contentWarningDescription; - StatusBaseViewHolder(View itemView) { + private boolean useAbsoluteTime; + + StatusBaseViewHolder(View itemView, boolean useAbsoluteTime) { super(itemView); container = itemView.findViewById(R.id.status_container); displayName = itemView.findViewById(R.id.status_display_name); @@ -95,6 +95,8 @@ 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; } protected abstract int getMediaPreviewHeight(Context context); @@ -130,8 +132,7 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { } protected void setCreatedAt(@Nullable Date createdAt) { - SharedPreferences defPrefs = PreferenceManager.getDefaultSharedPreferences(timestampInfo.getContext()); - if (defPrefs.getBoolean("absoluteTimeView", true)) { + if (useAbsoluteTime) { String time = "ERROR!"; if (createdAt != null) { SimpleDateFormat sdf; diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java index 88d5b718..d0ab5b8a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java @@ -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); diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java index fcd96e52..a1c94036 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusViewHolder.java @@ -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 diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/ThreadAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/ThreadAdapter.java index cf2fadb1..609c495f 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/ThreadAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/ThreadAdapter.java @@ -36,12 +36,14 @@ public class ThreadAdapter extends RecyclerView.Adapter { private List 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) { diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/TimelineAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/TimelineAdapter.java index 9c6ef9d4..6bf1d44b 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/TimelineAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/TimelineAdapter.java @@ -39,6 +39,7 @@ public final class TimelineAdapter extends RecyclerView.Adapter { private final AdapterDataSource dataSource; private final StatusActionListener statusListener; private boolean mediaPreviewEnabled; + private boolean useAbsoluteTime; public TimelineAdapter(AdapterDataSource 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()) @@ -98,6 +100,10 @@ public final class TimelineAdapter extends RecyclerView.Adapter { mediaPreviewEnabled = enabled; } + public void setUseAbsoluteTime(boolean useAbsoluteTime){ + this.useAbsoluteTime=useAbsoluteTime; + } + public boolean getMediaPreviewEnabled() { return mediaPreviewEnabled; } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java index a2c3c900..37418218 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java @@ -198,6 +198,8 @@ public class NotificationsFragment extends SFragment implements alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false); boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true); adapter.setMediaPreviewEnabled(mediaPreviewEnabled); + boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false); + adapter.setUseAbsoluteTime(useAbsoluteTime); recyclerView.setAdapter(adapter); notifications.clear(); diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/SearchFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/SearchFragment.kt index 9aca783e..81bb71b8 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/SearchFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/SearchFragment.kt @@ -50,6 +50,7 @@ class SearchFragment : SFragment(), StatusActionListener, Injectable { private var alwaysShowSensitiveMedia = false private var mediaPreviewEnabled = true + private var useAbsoluteTime = false 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) alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false) mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true) + useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false) searchRecyclerView.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL)) searchRecyclerView.layoutManager = LinearLayoutManager(view.context) - searchAdapter = SearchResultsAdapter(mediaPreviewEnabled, alwaysShowSensitiveMedia, this, this) + searchAdapter = SearchResultsAdapter(mediaPreviewEnabled, alwaysShowSensitiveMedia, this, this, useAbsoluteTime) searchRecyclerView.adapter = searchAdapter } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java index 62fe57c8..cac56e1d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java @@ -248,6 +248,8 @@ public class TimelineFragment extends SFragment implements alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false); boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true); adapter.setMediaPreviewEnabled(mediaPreviewEnabled); + boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false); + adapter.setUseAbsoluteTime(useAbsoluteTime); boolean filter = preferences.getBoolean("tabFilterHomeReplies", true); filterRemoveReplies = kind == Kind.HOME && !filter; @@ -605,7 +607,7 @@ public class TimelineFragment extends SFragment implements case "mediaPreviewEnabled": { boolean enabled = sharedPreferences.getBoolean("mediaPreviewEnabled", true); boolean oldMediaPreviewEnabled = adapter.getMediaPreviewEnabled(); - if(enabled != oldMediaPreviewEnabled) { + if (enabled != oldMediaPreviewEnabled) { adapter.setMediaPreviewEnabled(enabled); fullyRefresh(); } @@ -827,7 +829,7 @@ public class TimelineFragment extends SFragment implements } private void onFetchTimelineFailure(Exception exception, FetchEnd fetchEnd, int position) { - if(isAdded()) { + if (isAdded()) { swipeRefreshLayout.setRefreshing(false); if (fetchEnd == FetchEnd.MIDDLE && !statuses.get(position).isRight()) { @@ -1049,7 +1051,7 @@ public class TimelineFragment extends SFragment implements private final ListUpdateCallback listUpdateCallback = new ListUpdateCallback() { @Override public void onInserted(int position, int count) { - if(isAdded()) { + if (isAdded()) { adapter.notifyItemRangeInserted(position, count); Context context = getContext(); if (position == 0 && context != null) { diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java index 93cb0071..376fab60 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java @@ -156,6 +156,8 @@ public final class ViewThreadFragment extends SFragment implements alwaysShowSensitiveMedia = preferences.getBoolean("alwaysShowSensitiveMedia", false); boolean mediaPreviewEnabled = preferences.getBoolean("mediaPreviewEnabled", true); adapter.setMediaPreviewEnabled(mediaPreviewEnabled); + boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false); + adapter.setUseAbsoluteTime(useAbsoluteTime); recyclerView.setAdapter(adapter); statuses.clear(); From b4bb80c4d539369cab9bc936ba7131e3cac3bac3 Mon Sep 17 00:00:00 2001 From: kyori Date: Mon, 20 Aug 2018 17:47:19 +0900 Subject: [PATCH 6/9] Stop initializing String. --- .../com/keylesspalace/tusky/adapter/NotificationsAdapter.java | 2 +- .../com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java index ee69a5e4..5f9f5261 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java @@ -379,7 +379,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter { protected void setCreatedAt(@Nullable Date createdAt) { if (useAbsoluteTime) { - String time = "ERROR!"; + String time; if (createdAt != null) { SimpleDateFormat sdf; if (new Date().getTime() - createdAt.getTime() > 86400000L) { diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index b9191144..2384de8a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -133,7 +133,7 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { protected void setCreatedAt(@Nullable Date createdAt) { if (useAbsoluteTime) { - String time = "ERROR!"; + String time; if (createdAt != null) { SimpleDateFormat sdf; if (new Date().getTime() - createdAt.getTime() > 86400000L) { From 4264fc42d61136bf46bbc7bbc5a7db6159f47e0c Mon Sep 17 00:00:00 2001 From: kyori Date: Mon, 20 Aug 2018 19:29:58 +0900 Subject: [PATCH 7/9] Add process for when the createdAt is null. --- .../com/keylesspalace/tusky/adapter/NotificationsAdapter.java | 4 +++- .../com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java index 5f9f5261..4c937c4d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java @@ -388,8 +388,10 @@ public class NotificationsAdapter extends RecyclerView.Adapter { sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); } time = sdf.format(createdAt); - timestampInfo.setText(time); + } else { + time = "??:??:??"; } + timestampInfo.setText(time); } else { // This is the visible timestampInfo. String readout; diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index 2384de8a..185156f9 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -142,8 +142,10 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); } time = sdf.format(createdAt); - timestampInfo.setText(time); + } else { + time = "??:??:??"; } + timestampInfo.setText(time); } else { // This is the visible timestampInfo. String readout; From ad888854bc34ea5f78745266a29b27552d06e0d7 Mon Sep 17 00:00:00 2001 From: kyori Date: Mon, 20 Aug 2018 20:56:22 +0900 Subject: [PATCH 8/9] Use SimpleDateFormatter repeatedly. --- .../tusky/adapter/NotificationsAdapter.java | 14 +++++++++----- .../tusky/adapter/StatusBaseViewHolder.java | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java index 4c937c4d..248aa047 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java @@ -328,6 +328,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter { private StatusViewData.Concrete statusViewData; private boolean useAbsoluteTime; + private SimpleDateFormat sdf; + private boolean passed1day; StatusNotificationViewHolder(View itemView, boolean useAbsoluteTime) { super(itemView); @@ -353,6 +355,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter { contentWarningButton.setOnCheckedChangeListener(this); this.useAbsoluteTime = useAbsoluteTime; + sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); + passed1day = false; } private void showNotificationContent(boolean show) { @@ -381,11 +385,11 @@ public class NotificationsAdapter extends RecyclerView.Adapter { if (useAbsoluteTime) { String time; if (createdAt != null) { - SimpleDateFormat sdf; - if (new Date().getTime() - createdAt.getTime() > 86400000L) { - sdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault()); - } else { - sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); + if (!passed1day) { + if (new Date().getTime() - createdAt.getTime() > 86400000L) { + passed1day = true; + sdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault()); + } } time = sdf.format(createdAt); } else { diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index 185156f9..d3e0772b 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -67,6 +67,8 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { TextView contentWarningDescription; private boolean useAbsoluteTime; + private SimpleDateFormat sdf; + private boolean passed1day; StatusBaseViewHolder(View itemView, boolean useAbsoluteTime) { super(itemView); @@ -97,6 +99,8 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { contentWarningButton = itemView.findViewById(R.id.status_content_warning_button); this.useAbsoluteTime = useAbsoluteTime; + sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); + passed1day = false; } protected abstract int getMediaPreviewHeight(Context context); @@ -135,11 +139,11 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { if (useAbsoluteTime) { String time; if (createdAt != null) { - SimpleDateFormat sdf; - if (new Date().getTime() - createdAt.getTime() > 86400000L) { - sdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault()); - } else { - sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); + if (!passed1day) { + if (new Date().getTime() - createdAt.getTime() > 86400000L) { + passed1day = true; + sdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault()); + } } time = sdf.format(createdAt); } else { From 589188e27dcbdf383087d76c4defde1ad6a57653 Mon Sep 17 00:00:00 2001 From: kyori Date: Mon, 20 Aug 2018 22:51:30 +0900 Subject: [PATCH 9/9] Prevent creating new object in setCreatedAt --- .../tusky/adapter/NotificationsAdapter.java | 18 ++++++++---------- .../tusky/adapter/StatusBaseViewHolder.java | 18 ++++++++---------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java index 248aa047..8c2eb221 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java @@ -328,8 +328,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter { private StatusViewData.Concrete statusViewData; private boolean useAbsoluteTime; - private SimpleDateFormat sdf; - private boolean passed1day; + private SimpleDateFormat shortSdf; + private SimpleDateFormat longSdf; StatusNotificationViewHolder(View itemView, boolean useAbsoluteTime) { super(itemView); @@ -355,8 +355,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter { contentWarningButton.setOnCheckedChangeListener(this); this.useAbsoluteTime = useAbsoluteTime; - sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); - passed1day = false; + shortSdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); + longSdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault()); } private void showNotificationContent(boolean show) { @@ -385,13 +385,11 @@ public class NotificationsAdapter extends RecyclerView.Adapter { if (useAbsoluteTime) { String time; if (createdAt != null) { - if (!passed1day) { - if (new Date().getTime() - createdAt.getTime() > 86400000L) { - passed1day = true; - sdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault()); - } + if (System.currentTimeMillis() - createdAt.getTime() > 86400000L) { + time = longSdf.format(createdAt); + } else { + time = shortSdf.format(createdAt); } - time = sdf.format(createdAt); } else { time = "??:??:??"; } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index d3e0772b..2d7f0fa7 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -67,8 +67,8 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { TextView contentWarningDescription; private boolean useAbsoluteTime; - private SimpleDateFormat sdf; - private boolean passed1day; + private SimpleDateFormat shortSdf; + private SimpleDateFormat longSdf; StatusBaseViewHolder(View itemView, boolean useAbsoluteTime) { super(itemView); @@ -99,8 +99,8 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { contentWarningButton = itemView.findViewById(R.id.status_content_warning_button); this.useAbsoluteTime = useAbsoluteTime; - sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); - passed1day = false; + shortSdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); + longSdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault()); } protected abstract int getMediaPreviewHeight(Context context); @@ -139,13 +139,11 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { if (useAbsoluteTime) { String time; if (createdAt != null) { - if (!passed1day) { - if (new Date().getTime() - createdAt.getTime() > 86400000L) { - passed1day = true; - sdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault()); - } + if (System.currentTimeMillis() - createdAt.getTime() > 86400000L) { + time = longSdf.format(createdAt); + } else { + time = shortSdf.format(createdAt); } - time = sdf.format(createdAt); } else { time = "??:??:??"; }