diff --git a/Habitica/res/layout/fragment_gift_gem_balance.xml b/Habitica/res/layout/fragment_gift_gem_balance.xml
index 614f6c32b..a1f4f3532 100644
--- a/Habitica/res/layout/fragment_gift_gem_balance.xml
+++ b/Habitica/res/layout/fragment_gift_gem_balance.xml
@@ -75,5 +75,10 @@
style="@style/HabiticaButton.Purple"
android:layout_marginTop="@dimen/spacing_medium"
android:text="@string/send_gift" />
+
\ No newline at end of file
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index c4ac3fda7..5d3ffe647 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -747,7 +747,7 @@
Your gift was sent!
You sent %1$s a %2$s-month Habitica subscription and the same subscription was applied to your account for our Gift One Get One promotion!
You sent @%1$s a %2$s-month Habitica subscription.
- You sent @%s %s gems.
+ You sent @%1$s %2$s gems.
You are now subscribed for 1 month
You are now subscribed for %s months
You gained %s gems.
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt
index 0e507d1fc..75933a88e 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SocialRepositoryImpl.kt
@@ -89,11 +89,10 @@ class SocialRepositoryImpl(
return null
}
val liked = chatMessage.userLikesMessage(userID)
- if (chatMessage.isManaged) {
- localRepository.likeMessage(chatMessage, userID, !liked)
- }
+ localRepository.likeMessage(chatMessage, userID, !liked)
val message = apiClient.likeMessage(chatMessage.groupId ?: "", chatMessage.id)
message?.groupId = chatMessage.groupId
+ message?.let { localRepository.save(it) }
return null
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PurchaseHandler.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PurchaseHandler.kt
index 1222416d5..7c8b3b0e3 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PurchaseHandler.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PurchaseHandler.kt
@@ -211,7 +211,9 @@ class PurchaseHandler(
}
val flowParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(listOf(skuDetails).map {
- BillingFlowParams.ProductDetailsParams.newBuilder().setProductDetails(skuDetails)
+ BillingFlowParams.ProductDetailsParams.newBuilder()
+ .setProductDetails(skuDetails)
+ .setOfferToken(skuDetails.subscriptionOfferDetails?.first()?.offerToken ?: "")
.build()
})
.build()
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/notifications/PushNotificationManager.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/notifications/PushNotificationManager.kt
index fb14775c2..79adfd5c4 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/notifications/PushNotificationManager.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/notifications/PushNotificationManager.kt
@@ -11,6 +11,7 @@ import com.habitrpg.android.habitica.helpers.AmplitudeManager
import com.habitrpg.android.habitica.helpers.launchCatching
import com.habitrpg.android.habitica.models.user.User
import kotlinx.coroutines.MainScope
+import java.io.IOException
class PushNotificationManager(
var apiClient: ApiClient,
@@ -52,8 +53,12 @@ class PushNotificationManager(
addRefreshToken()
} else {
FirebaseMessaging.getInstance().token.addOnCompleteListener {
- refreshedToken = it.result
- addRefreshToken()
+ try {
+ refreshedToken = it.result
+ addRefreshToken()
+ } catch (_: IOException) {
+ // This can happen during google test runs
+ }
}
}
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.kt
index acc6756d5..d67256641 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/LoginActivity.kt
@@ -126,7 +126,6 @@ class LoginActivity : BaseActivity() {
}
override fun getLayoutResId(): Int {
- window.requestFeature(Window.FEATURE_ACTION_BAR)
return R.layout.activity_login
}
@@ -136,6 +135,7 @@ class LoginActivity : BaseActivity() {
}
override fun onCreate(savedInstanceState: Bundle?) {
+ window.requestFeature(Window.FEATURE_ACTION_BAR)
super.onCreate(savedInstanceState)
viewModel = AuthenticationViewModel()
supportActionBar?.hide()
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationEquipmentRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationEquipmentRecyclerViewAdapter.kt
index 39bdd2d16..c111d3dfd 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationEquipmentRecyclerViewAdapter.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationEquipmentRecyclerViewAdapter.kt
@@ -111,7 +111,7 @@ class CustomizationEquipmentRecyclerViewAdapter : androidx.recyclerview.widget.R
imageView.loadImage("shop_" + this.equipment?.key)
val priceLabel = dialogContent.findViewById(R.id.priceLabel)
- priceLabel.text = if (equipment?.gearSet == "animal") {
+ priceLabel?.text = if (equipment?.gearSet == "animal") {
2.0
} else {
equipment?.value ?: 0
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt
index 924ca94f3..4215b112d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt
@@ -335,7 +335,7 @@ class AvatarCustomizationFragment :
button.setOnCheckedChangeListener { _, isChecked ->
val newFilter = filter.copy()
newFilter.months = mutableListOf()
- newFilter.months.addAll(filter.months)
+ newFilter.months.addAll(currentFilter.value.months)
if (!isChecked && newFilter.months.contains(identifier)) {
button.typeface = Typeface.create("sans-serif", Typeface.NORMAL)
newFilter.months.remove(identifier)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GiftBalanceGemsFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GiftBalanceGemsFragment.kt
index 4dde1b73f..ac78413e9 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GiftBalanceGemsFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/purchases/GiftBalanceGemsFragment.kt
@@ -5,28 +5,41 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
+import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.databinding.FragmentGiftGemBalanceBinding
+import com.habitrpg.android.habitica.extensions.addCloseButton
import com.habitrpg.android.habitica.helpers.launchCatching
import com.habitrpg.android.habitica.models.members.Member
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
+import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import javax.inject.Inject
class GiftBalanceGemsFragment : BaseFragment() {
@Inject
lateinit var socialRepository: SocialRepository
+
@Inject
lateinit var userRepository: UserRepository
override var binding: FragmentGiftGemBalanceBinding? = null
private var isGifting = false
+ set(value) {
+ field = value
+ binding?.giftButton?.isVisible = !isGifting
+ binding?.progressBar?.isVisible = isGifting
+ }
- override fun createBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentGiftGemBalanceBinding {
+ override fun createBinding(
+ inflater: LayoutInflater,
+ container: ViewGroup?
+ ): FragmentGiftGemBalanceBinding {
return FragmentGiftGemBalanceBinding.inflate(inflater, container, false)
}
@@ -61,15 +74,29 @@ class GiftBalanceGemsFragment : BaseFragment() {
if (isGifting) return
isGifting = true
try {
- val amount = binding?.giftEditText?.text.toString().toInt()
+ val amount = binding?.giftEditText?.text.toString().strip().toInt()
giftedMember?.id?.let {
- lifecycleScope.launchCatching({
+ activity?.lifecycleScope?.launchCatching({
isGifting = false
}) {
socialRepository.transferGems(it, amount)
userRepository.retrieveUser(false)
+ val dialog = context?.let { it1 -> HabiticaAlertDialog(it1) }
+ dialog?.setTitle(R.string.gift_confirmation_title)
+ dialog?.setMessage(
+ getString(
+ R.string.gift_confirmation_text_gems_new,
+ giftedMember?.username,
+ amount.toString()
+ )
+ )
+ dialog?.addCloseButton { _, _ ->
+ activity?.finish()
+ }
+ dialog?.show()
}
}
- } catch (ignored: NumberFormatException) {}
+ } catch (ignored: NumberFormatException) {
+ }
}
}
diff --git a/common/src/main/java/com/habitrpg/common/habitica/helpers/MarkdownParser.kt b/common/src/main/java/com/habitrpg/common/habitica/helpers/MarkdownParser.kt
index 1b28948cb..adeb49fc2 100644
--- a/common/src/main/java/com/habitrpg/common/habitica/helpers/MarkdownParser.kt
+++ b/common/src/main/java/com/habitrpg/common/habitica/helpers/MarkdownParser.kt
@@ -91,8 +91,12 @@ object MarkdownParser {
return SpannableString("")
}
val hashCode = input.hashCode()
- if (cache.containsKey(hashCode)) {
- return cache[hashCode] ?: SpannableString(input)
+ try {
+ if (cache.containsKey(hashCode)) {
+ return cache[hashCode] ?: SpannableString(input)
+ }
+ } catch (_: NullPointerException) {
+ // Sometimes happens
}
val text = EmojiParser.parseEmojis(input) ?: input
// Adding this space here bc for some reason some markdown is not rendered correctly when the whole string is supposed to be formatted
diff --git a/fastlane/changelog.txt b/fastlane/changelog.txt
index 13189c062..fd05a0cc1 100644
--- a/fastlane/changelog.txt
+++ b/fastlane/changelog.txt
@@ -1,9 +1,12 @@
New in 4.1:
--You can view, complete, assign, and add tasks to your Group Plan’s shared task board!
+-You can view, complete, assign, and add tasks to your Group Plan's shared task board!
-Tap your name on a task screen to switch to different task boards
--Subscription details will show extra months and when you’ll get your next Hourglass
--More intuitive system notification settings
--Audio will be controlled by media volume now
-Task details are now tinted based on task health
+-New Avatar Customization interface
+-Audio will be controlled by media volume now
-Fixed a bug that caused tasks to shuffle around
-Monthly Dailies should recur more consistently now
+-More intuitive system notification settings
+-Improved link support
+-More special event support
+
diff --git a/version.properties b/version.properties
index 19dae3716..8c685bc20 100644
--- a/version.properties
+++ b/version.properties
@@ -1,2 +1,2 @@
NAME=4.1
-CODE=4981
\ No newline at end of file
+CODE=4991
\ No newline at end of file