diff --git a/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/GiftMessageView.kt b/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/GiftMessageView.kt
index 4177e264a..9aa46b919 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/GiftMessageView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/GiftMessageView.kt
@@ -13,6 +13,7 @@ import com.google.android.material.button.MaterialButton
import org.signal.core.util.DimensionUnit
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.badges.BadgeImageView
+import org.thoughtcrime.securesms.badges.gifts.Gifts.formatExpiry
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
import org.thoughtcrime.securesms.mms.GlideRequests
@@ -50,7 +51,7 @@ class GiftMessageView @JvmOverloads constructor(
fun setGiftBadge(glideRequests: GlideRequests, giftBadge: GiftBadge, isOutgoing: Boolean, callback: Callback) {
titleView.setText(R.string.GiftMessageView__gift_badge)
- descriptionView.text = resources.getQuantityString(R.plurals.GiftMessageView__lasts_for_d_months, 1, 1)
+ descriptionView.text = giftBadge.formatExpiry(context)
actionView.icon = null
actionView.setOnClickListener { callback.onViewGiftBadgeClicked() }
actionView.isEnabled = true
diff --git a/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/Gifts.kt b/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/Gifts.kt
index 938032d69..afdd45602 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/Gifts.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/Gifts.kt
@@ -1,5 +1,9 @@
package org.thoughtcrime.securesms.badges.gifts
+import android.content.Context
+import org.signal.libsignal.zkgroup.InvalidInputException
+import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialPresentation
+import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.database.model.StoryType
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
@@ -7,6 +11,8 @@ import org.thoughtcrime.securesms.mms.OutgoingMediaMessage
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.Base64
+import java.lang.Integer.min
+import java.util.concurrent.TimeUnit
/**
* Helper object for Gift badges
@@ -45,4 +51,36 @@ object Gifts {
giftBadge
)
}
+
+ /**
+ * @return the expiration time from the redemption token, in UNIX epoch seconds.
+ */
+ private fun GiftBadge.getExpiry(): Long {
+ return try {
+ ReceiptCredentialPresentation(redemptionToken.toByteArray()).receiptExpirationTime
+ } catch (e: InvalidInputException) {
+ return 0L
+ }
+ }
+
+ fun GiftBadge.formatExpiry(context: Context): String {
+ val expiry = getExpiry()
+ val timeRemaining = TimeUnit.SECONDS.toMillis(expiry) - System.currentTimeMillis()
+ if (timeRemaining <= 0) {
+ return context.getString(R.string.Gifts__expired)
+ }
+
+ val days = TimeUnit.MILLISECONDS.toDays(timeRemaining).toInt()
+ if (days > 0) {
+ return context.resources.getQuantityString(R.plurals.Gifts__d_days_remaining, days, days)
+ }
+
+ val hours = TimeUnit.MILLISECONDS.toHours(timeRemaining).toInt()
+ if (hours > 0) {
+ return context.resources.getQuantityString(R.plurals.Gifts__d_hours_remaining, hours, hours)
+ }
+
+ val minutes = min(1, TimeUnit.MILLISECONDS.toMinutes(timeRemaining).toInt())
+ return context.resources.getQuantityString(R.plurals.Gifts__d_minutes_remaining, minutes, minutes)
+ }
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a658bc8fd..f1f7615c4 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -4824,6 +4824,23 @@
- Group Story · %1$d viewer
- Group Story · %1$d viewers
+
+
+ - %1$d days remaining
+ - %1$d days remaining
+
+
+
+ - %1$d hours remaining
+ - %1$d hours remaining
+
+
+
+ - %1$d minute remaining
+ - %1$d minutes remaining
+
+
+ Expired