diff --git a/app/src/main/java/app/pachli/components/announcements/AnnouncementAdapter.kt b/app/src/main/java/app/pachli/components/announcements/AnnouncementAdapter.kt index 8910d6c08..144ac18d3 100644 --- a/app/src/main/java/app/pachli/components/announcements/AnnouncementAdapter.kt +++ b/app/src/main/java/app/pachli/components/announcements/AnnouncementAdapter.kt @@ -27,9 +27,12 @@ import app.pachli.R import app.pachli.databinding.ItemAnnouncementBinding import app.pachli.entity.Announcement import app.pachli.interfaces.LinkListener +import app.pachli.util.AbsoluteTimeFormatter import app.pachli.util.BindingHolder import app.pachli.util.EmojiSpan import app.pachli.util.emojify +import app.pachli.util.equalByMinute +import app.pachli.util.getRelativeTimeSpanString import app.pachli.util.parseAsMastodonHtml import app.pachli.util.setClickableText import app.pachli.util.visible @@ -48,7 +51,9 @@ class AnnouncementAdapter( private val listener: AnnouncementActionListener, private val wellbeingEnabled: Boolean = false, private val animateEmojis: Boolean = false, + private val useAbsoluteTime: Boolean = false, ) : RecyclerView.Adapter>() { + private val absoluteTimeFormatter = AbsoluteTimeFormatter() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder { val binding = ItemAnnouncementBinding.inflate(LayoutInflater.from(parent.context), parent, false) @@ -57,6 +62,29 @@ class AnnouncementAdapter( override fun onBindViewHolder(holder: BindingHolder, position: Int) { val item = items[position] + val now = System.currentTimeMillis() + + val publishTimeToDisplay = if (useAbsoluteTime) { + absoluteTimeFormatter.format(item.publishedAt, shortFormat = item.allDay) + } else { + getRelativeTimeSpanString(holder.binding.root.context, item.publishedAt.time, now) + } + + val updatedAtText = if (item.updatedAt.equalByMinute(item.publishedAt)) { + // they're the same, don't show the "updated" indicator + "" + } else { + // they're a minute or more apart, show the "updated" indicator + val formattedUpdatedAt = if (useAbsoluteTime) { + absoluteTimeFormatter.format(item.updatedAt, item.allDay) + } else { + getRelativeTimeSpanString(holder.binding.root.context, item.updatedAt.time, now) + } + holder.binding.root.context.getString(R.string.announcement_date_updated, formattedUpdatedAt) + } + + val announcementDate = holder.binding.root.context.getString(R.string.announcement_date, publishTimeToDisplay, updatedAtText) + holder.binding.announcementDate.text = announcementDate val text = holder.binding.text val chips = holder.binding.chipGroup @@ -88,7 +116,8 @@ class AnnouncementAdapter( ) .apply { if (reaction.url == null) { - this.text = "${reaction.name} ${reaction.count}" + val reactionNameAndCountText = holder.binding.root.context.getString(R.string.reaction_name_and_count, reaction.name, reaction.count) + this.text = reactionNameAndCountText } else { // we set the EmojiSpan on a space, because otherwise the Chip won't have the right size // https://github.com/tuskyapp/Tusky/issues/2308 diff --git a/app/src/main/java/app/pachli/components/announcements/AnnouncementsActivity.kt b/app/src/main/java/app/pachli/components/announcements/AnnouncementsActivity.kt index 63e8970f9..65f5767dd 100644 --- a/app/src/main/java/app/pachli/components/announcements/AnnouncementsActivity.kt +++ b/app/src/main/java/app/pachli/components/announcements/AnnouncementsActivity.kt @@ -98,8 +98,9 @@ class AnnouncementsActivity : val wellbeingEnabled = sharedPreferencesRepository.getBoolean(PrefKeys.WELLBEING_HIDE_STATS_POSTS, false) val animateEmojis = sharedPreferencesRepository.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) + val useAbsoluteTime = sharedPreferencesRepository.getBoolean(PrefKeys.ABSOLUTE_TIME_VIEW, false) - adapter = AnnouncementAdapter(emptyList(), this, wellbeingEnabled, animateEmojis) + adapter = AnnouncementAdapter(emptyList(), this, wellbeingEnabled, animateEmojis, useAbsoluteTime) binding.announcementsList.adapter = adapter diff --git a/app/src/main/java/app/pachli/util/DateExtensions.kt b/app/src/main/java/app/pachli/util/DateExtensions.kt new file mode 100644 index 000000000..8ce27ec5d --- /dev/null +++ b/app/src/main/java/app/pachli/util/DateExtensions.kt @@ -0,0 +1,18 @@ +package app.pachli.util + +import java.util.Date + +/** + * Compares this [Date] with [other], and returns true if they are equal to within the same + * minute. + * + * "Same minute" means "they are within the same clock minute", not "they are within 60 seconds + * of each other". + */ +fun Date.equalByMinute(other: Date): Boolean { + return this.minutes == other.minutes && + this.hours == other.hours && + this.date == other.date && + this.month == other.month && + this.year == other.year +} diff --git a/app/src/main/res/layout/item_announcement.xml b/app/src/main/res/layout/item_announcement.xml index 4e1d0df0d..b6021f990 100644 --- a/app/src/main/res/layout/item_announcement.xml +++ b/app/src/main/res/layout/item_announcement.xml @@ -6,6 +6,7 @@ + app:layout_constraintTop_toBottomOf="@id/text" + app:layout_constraintBottom_toTopOf="@id/announcementDate"> + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6929167d2..855bbc440 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -745,6 +745,8 @@ Compose Post Joined %1$s + (Updated: %1$s) + %1$s %2$s Saving draft… @@ -824,4 +826,6 @@ Delete filter \'%1$s\'?" Delete Do you want to save your profile changes? + + %1$s %2$d