diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index 5a679bf05..615932057 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -1146,5 +1146,6 @@
Are you sure you want to leave the Quest? You won\'t be able to participate.
Launch Screen
New
- Limited Items Available
+ Seasonal Items Available
+ Open for %s
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/Date-Extensions.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/Date-Extensions.kt
index cd0daed6e..c9206a80b 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/Date-Extensions.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/extensions/Date-Extensions.kt
@@ -97,13 +97,18 @@ fun Long.getShortRemainingString(): String {
val diffHours = diff / (60 * 60 * 1000)
diff -= (diffHours * (60 * 60 * 1000))
val diffMinutes = diff / (60 * 1000)
+ diff -= (diffMinutes * (60 * 1000))
+ val diffSeconds = diff / 1000
var str = "${diffMinutes}m"
if (diffHours > 0) {
- str = "${diffHours}h ${str}"
+ str = "${diffHours}h $str"
}
if (diffDays > 0) {
- str = "${diffDays}d ${str}"
+ str = "${diffDays}d $str"
+ }
+ if (diffDays == 0L && diffHours == 0L) {
+ str = "$str ${diffSeconds}s"
}
return str
}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/WorldState.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/WorldState.kt
index 6192d2f8f..23bdf774c 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/WorldState.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/WorldState.kt
@@ -6,9 +6,12 @@ import com.habitrpg.android.habitica.models.inventory.QuestRageStrike
import io.realm.RealmList
import io.realm.RealmModel
import io.realm.RealmObject
+import io.realm.annotations.PrimaryKey
import java.util.*
open class WorldState: RealmObject() {
+ @PrimaryKey
+ var id = "habitica"
var worldBossKey: String = ""
var worldBossActive: Boolean = false
var progress: QuestProgress? = null
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
index 74e2dd48f..0ccf6f49b 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
@@ -19,10 +19,7 @@ import com.habitrpg.android.habitica.data.InventoryRepository
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.databinding.DrawerMainBinding
-import com.habitrpg.android.habitica.extensions.getRemainingString
-import com.habitrpg.android.habitica.extensions.getThemeColor
-import com.habitrpg.android.habitica.extensions.isUsingNightModeResources
-import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
+import com.habitrpg.android.habitica.extensions.*
import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.helpers.RxErrorHandler
@@ -41,10 +38,14 @@ import com.habitrpg.android.habitica.ui.menu.HabiticaDrawerItem
import com.habitrpg.android.habitica.ui.viewmodels.NotificationsViewModel
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
import io.reactivex.rxjava3.disposables.CompositeDisposable
+import kotlinx.coroutines.*
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.collections.ArrayList
+import kotlin.time.ExperimentalTime
+import kotlin.time.minutes
+import kotlin.time.seconds
class NavigationDrawerFragment : DialogFragment() {
@@ -168,6 +169,9 @@ class NavigationDrawerFragment : DialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.drawer_main, container, false) as? ViewGroup
+ private var seasonalShopJob: Job? = null
+
+ @OptIn(ExperimentalTime::class)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = DrawerMainBinding.bind(view)
@@ -192,8 +196,19 @@ class NavigationDrawerFragment : DialogFragment() {
state.events.forEach {
if (it.gear) {
val shop = getItemWithIdentifier(SIDEBAR_SHOPS_SEASONAL) ?: return@forEach
- shop.isVisible = true
shop.pillText = context?.getString(R.string.open)
+ seasonalShopJob?.cancel()
+ seasonalShopJob = GlobalScope.launch(Dispatchers.Main) {
+ while (it.end?.after(Date()) == true) {
+ shop.isVisible = true
+ shop.subtitle = context?.getString(R.string.open_for, it.end?.getShortRemainingString())
+ val diff = (it.end?.time ?: 0) - Date().time
+ delay(if (diff < (60 * 60 * 1000)) 1.seconds else 1.minutes)
+ adapter.notifyDataSetChanged()
+ }
+ shop.isVisible = false
+ adapter.notifyDataSetChanged()
+ }
return@subscribe
}
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt
index c6a7adc2d..63f01f08e 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt
@@ -42,10 +42,17 @@ import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.realm.RealmResults
+import kotlinx.coroutines.*
import org.greenrobot.eventbus.EventBus
+import java.time.Duration
+import java.time.temporal.TemporalUnit
import java.util.*
import javax.inject.Inject
import kotlin.math.max
+import kotlin.time.DurationUnit
+import kotlin.time.ExperimentalTime
+import kotlin.time.minutes
+import kotlin.time.seconds
class PurchaseDialog(context: Context, component: UserComponent?, val item: ShopItem) : HabiticaAlertDialog(context) {
@@ -159,14 +166,24 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop
setLimitedTextView()
}
+ private var limitedTextViewJob: Job? = null
+
+ @OptIn(ExperimentalTime::class)
private fun setLimitedTextView() {
if (shopItem.habitClass != null && shopItem.habitClass != "special" && user?.stats?.habitClass != shopItem.habitClass) {
limitedTextView.text = context.getString(R.string.class_equipment_shop_dialog)
limitedTextView.visibility = View.VISIBLE
limitedTextView.setBackgroundColor(ContextCompat.getColor(context, R.color.inverted_background))
} else if (shopItem.event?.end?.after(Date()) == true) {
- limitedTextView.visibility = View.VISIBLE
- limitedTextView.text = context.getString(R.string.available_for, shopItem.event?.end?.getShortRemainingString())
+ limitedTextViewJob?.cancel()
+ limitedTextViewJob = GlobalScope.launch(Dispatchers.Main) {
+ limitedTextView.visibility = View.VISIBLE
+ while (shopItem.event?.end?.after(Date()) == true) {
+ limitedTextView.text = context.getString(R.string.available_for, shopItem.event?.end?.getShortRemainingString())
+ val diff = (shopItem.event?.end?.time ?: 0) - Date().time
+ delay(if (diff < (60 * 60 * 1000)) 1.seconds else 1.minutes)
+ }
+ }
} else if (shopItem.locked) {
buyLabel.text = context.getString(R.string.locked)
limitedTextView.visibility = View.VISIBLE
@@ -256,6 +273,7 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop
override fun dismiss() {
userRepository.close()
inventoryRepository.close()
+ limitedTextViewJob?.cancel()
if (!compositeSubscription.isDisposed) {
compositeSubscription.dispose()
}
diff --git a/Habitica/src/test/java/com/habitrpg/android/habitica/extensions/Date_ExtensionsKtTest.kt b/Habitica/src/test/java/com/habitrpg/android/habitica/extensions/Date_ExtensionsKtTest.kt
index 9911e8bd9..34684e75f 100644
--- a/Habitica/src/test/java/com/habitrpg/android/habitica/extensions/Date_ExtensionsKtTest.kt
+++ b/Habitica/src/test/java/com/habitrpg/android/habitica/extensions/Date_ExtensionsKtTest.kt
@@ -14,6 +14,6 @@ class DateExtensionsTest : TestCase() {
}
fun testGetShortRemainingStringWithMinute() {
- assertEquals("34m", (Date().time + 2077400L).getShortRemainingString())
+ assertEquals("34m 37s", (Date().time + 2077400L).getShortRemainingString())
}
}
\ No newline at end of file