customization improvements

This commit is contained in:
Phillip Thelen 2020-04-08 17:59:46 +02:00
parent 01f0ac5a4a
commit 8eff8c6a5a
12 changed files with 81 additions and 91 deletions

View file

@ -155,7 +155,7 @@ android {
multiDexEnabled true
resConfigs "en", "bg", "de", "en-rGB", "es", "fr", "hr-rHR", "in", "it", "iw", "ja", "ko", "lt", "nl", "pl", "pt-rBR", "pt-rPT", "ru", "tr", "zh", "zh-rTW"
versionCode 2394
versionCode 2396
versionName "2.5"
}

View file

@ -104,11 +104,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/avatar_animal_ears_view"
android:visibility="gone"
app:equipmentTitle="@string/animal_ears"/>
<com.habitrpg.android.habitica.ui.views.EquipmentItemRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/avatar_animal_tail_view"
android:visibility="gone"
app:equipmentTitle="@string/animal_tail"/>
<com.habitrpg.android.habitica.ui.views.EquipmentItemRow
android:layout_width="match_parent"

View file

@ -140,7 +140,7 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli
}
res._tmp?.drop?.key?.let { key ->
val type = when(res._tmp?.drop?.type?.toLowerCase(Locale.US)) {
"hatchingPotion" -> "hatchingPotions"
"hatchingpotion" -> "hatchingPotions"
"egg" -> "eggs"
else -> res._tmp?.drop?.type?.toLowerCase(Locale.US)
}

View file

@ -27,12 +27,10 @@ class RealmCustomizationLocalRepository(realm: Realm) : RealmContentLocalReposit
.isNull("availableFrom")
.isNull("availableUntil")
.endGroup()
.or()
.equalTo("purchased", true)
.endGroup()
}
return query
.sort("customizationSet")
.sort("customizationSetName")
.findAll()
.asFlowable()
.filter { it.isLoaded }

View file

@ -26,7 +26,6 @@ open class Customization : RealmObject() {
var customizationSet: String? = null
var customizationSetName: String? = null
var text: String? = null
var purchased = false
var isBuyable = false
var price: Int? = null
var setPrice: Int? = null
@ -48,7 +47,7 @@ open class Customization : RealmObject() {
fun getIconName(userSize: String?, hairColor: String?): String {
return if (type == "background") {
"background_$identifier"
"icon_background_$identifier"
} else {
getImageName(userSize, hairColor)
}
@ -73,8 +72,9 @@ open class Customization : RealmObject() {
return ""
}
val isUsable: Boolean
get() = price == null || price == 0 || purchased
fun isUsable(purchased: Boolean): Boolean {
return price == null || price == 0 || purchased
}
val path: String
get() {
@ -82,8 +82,7 @@ open class Customization : RealmObject() {
if (this.category != null) {
path = path + "." + this.category
}
path = path + "." + identifier
path = "$path.$identifier"
return path
}
}

View file

@ -0,0 +1,28 @@
package com.habitrpg.android.habitica.models.user
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
open class OwnedCustomization : RealmObject(), OwnedObject {
@PrimaryKey
override var combinedKey: String? = null
override var userID: String? = null
set(value) {
field = value
combinedKey = field + type + key
}
override var key: String? = null
set(value) {
field = value
combinedKey = userID + type + field
}
var type: String? = null
set(value) {
field = value
combinedKey = userID + field + key
}
var category: String? = null
var purchased = false
}

View file

@ -1,7 +1,5 @@
package com.habitrpg.android.habitica.models.user;
import com.habitrpg.android.habitica.models.inventory.Customization;
import java.util.List;
import io.realm.RealmList;
@ -13,15 +11,15 @@ public class Purchases extends RealmObject {
@PrimaryKey
private String userId;
public RealmList<Customization> customizations;
public RealmList<OwnedCustomization> customizations;
User user;
private SubscriptionPlan plan;
public List<Customization> getCustomizations() {
public List<OwnedCustomization> getCustomizations() {
return customizations;
}
public void setCustomizations(RealmList<Customization> customizations) {
public void setCustomizations(RealmList<OwnedCustomization> customizations) {
this.customizations = customizations;
}

View file

@ -42,20 +42,15 @@ class CustomizationRecyclerViewAdapter : androidx.recyclerview.widget.RecyclerVi
this.notifyDataSetChanged()
}
var ownedCustomiztations: List<String> = listOf()
private val selectCustomizationEvents = PublishSubject.create<Customization>()
private val unlockCustomizationEvents = PublishSubject.create<Customization>()
private val unlockSetEvents = PublishSubject.create<CustomizationSet>()
fun updateOwnership(ownedCustomizations: List<String>) {
for ((position, obj) in customizationList.withIndex()) {
if (obj.javaClass == Customization::class.java) {
val customization = obj as? Customization ?: return
if (customization.purchased != ownedCustomizations.contains(customization.id)) {
customization.purchased = ownedCustomizations.contains(customization.id)
notifyItemChanged(position)
}
}
}
this.ownedCustomiztations = ownedCustomizations
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder {
@ -103,12 +98,12 @@ class CustomizationRecyclerViewAdapter : androidx.recyclerview.widget.RecyclerVi
set.identifier = customization.customizationSet
set.text = customization.customizationSetName
set.price = customization.setPrice
set.hasPurchasable = !customization.isUsable
set.hasPurchasable = !customization.isUsable(ownedCustomiztations.contains(customization.identifier))
lastSet = set
customizationList.add(set)
}
customizationList.add(customization)
if (!customization.isUsable && !lastSet.hasPurchasable) {
if (!customization.isUsable(ownedCustomiztations.contains(customization.identifier)) && !lastSet.hasPurchasable) {
lastSet.hasPurchasable = true
}
}
@ -148,7 +143,7 @@ class CustomizationRecyclerViewAdapter : androidx.recyclerview.widget.RecyclerVi
binding.imageView.layoutParams = params
}
if (customization.isUsable) {
if (customization.isUsable(ownedCustomiztations.contains(customization.identifier))) {
binding.buyButton.visibility = View.GONE
} else {
binding.buyButton.visibility = View.VISIBLE
@ -168,7 +163,7 @@ class CustomizationRecyclerViewAdapter : androidx.recyclerview.widget.RecyclerVi
}
override fun onClick(v: View) {
if (customization?.isUsable == false) {
if (customization?.isUsable(ownedCustomiztations.contains(customization?.identifier)) == false) {
if (customization?.customizationSet?.contains("timeTravel") == true) {
val dialog = HabiticaAlertDialog(itemView.context)
dialog.setMessage(R.string.purchase_from_timetravel_shop)
@ -256,11 +251,11 @@ class CustomizationRecyclerViewAdapter : androidx.recyclerview.widget.RecyclerVi
customizationList
.filter { Customization::class.java.isAssignableFrom(it.javaClass) }
.map { it as Customization }
.filter { !it.isUsable && it.customizationSet != null && it.customizationSet == set?.identifier }
.filter { !it.isUsable(ownedCustomiztations.contains(it.identifier)) && it.customizationSet != null && it.customizationSet == set?.identifier }
.forEach { set?.customizations?.add(it) }
if (additionalSetItems.isNotEmpty()) {
additionalSetItems
.filter { !it.isUsable && it.customizationSet != null && it.customizationSet == set?.identifier }
.filter { !it.isUsable(ownedCustomiztations.contains(it.identifier)) && it.customizationSet != null && it.customizationSet == set?.identifier }
.forEach { set?.customizations?.add(it) }
}
set?.let {

View file

@ -138,7 +138,7 @@ class AvatarCustomizationFragment : BaseMainFragment() {
this.updateActiveCustomization(user)
if (adapter.customizationList.size != 0) {
val ownedCustomizations = ArrayList<String>()
user.purchased?.customizations?.filter { it.type == this.type }?.mapTo(ownedCustomizations) { it.id ?: "" }
user.purchased?.customizations?.filter { it.type == this.type && it.purchased }?.mapTo(ownedCustomizations) { it.key ?: "" }
adapter.updateOwnership(ownedCustomizations)
} else {
this.loadCustomizations()

View file

@ -166,6 +166,7 @@ object DataBindingUtils {
tempMap["Mount_Body_Gryphon-Gryphatrice"] = "gif"
tempMap["background_clocktower"] = "gif"
tempMap["background_airship"] = "gif"
tempMap["background_steamwork"] = "gif"
tempMap["Pet_HatchingPotion_Veggie"] = "gif"
tempMap["Pet_HatchingPotion_Dessert"] = "gif"
tempMap["Pet-HatchingPotion-Dessert"] = "gif"

View file

@ -16,9 +16,8 @@ class CustomizationDeserializer : JsonDeserializer<List<Customization>> {
val customizations = RealmList<Customization>()
val realm = Realm.getDefaultInstance()
val existingCustomizations = realm.copyFromRealm(realm.where(Customization::class.java).findAll())
if (jsonObject.has("shirt")) {
val existingCustomizations = realm.copyFromRealm(realm.where(Customization::class.java).findAll())
for (customization in existingCustomizations) {
if (jsonObject.has(customization.type)) {
var nestedObject = jsonObject.get(customization.type).asJsonObject
@ -48,8 +47,6 @@ class CustomizationDeserializer : JsonDeserializer<List<Customization>> {
}
}
} else {
val existingCustomizations = realm.copyFromRealm(realm.where(Customization::class.java).findAll())
for (customization in existingCustomizations) {
if (jsonObject.has(customization.customizationSet)) {
val nestedObject = jsonObject.get(customization.customizationSet).asJsonObject
@ -123,19 +120,23 @@ class CustomizationDeserializer : JsonDeserializer<List<Customization>> {
customization.type = "background"
customization.identifier = key
}
if ("incentiveBackgrounds" == setName) {
customization.customizationSetName = "Login Incentive"
customization.price = 0
customization.setPrice = 0
customization.isBuyable = false
} else if ("timeTravelBackgrounds" == setName) {
customization.customizationSetName = "Time Travel Backgrounds"
customization.price = 1
customization.setPrice = 0
customization.isBuyable = false
} else {
customization.price = 7
customization.setPrice = 15
when (setName) {
"incentiveBackgrounds" -> {
customization.customizationSetName = "Login Incentive"
customization.price = 0
customization.setPrice = 0
customization.isBuyable = false
}
"timeTravelBackgrounds" -> {
customization.customizationSetName = "Time Travel Backgrounds"
customization.price = 1
customization.setPrice = 0
customization.isBuyable = false
}
else -> {
customization.price = 7
customization.setPrice = 15
}
}
customization.text = entry.get("text").asString

View file

@ -5,17 +5,14 @@ import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.habitrpg.android.habitica.models.inventory.Customization;
import com.habitrpg.android.habitica.models.user.OwnedCustomization;
import com.habitrpg.android.habitica.models.user.Purchases;
import com.habitrpg.android.habitica.models.user.SubscriptionPlan;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import io.realm.Realm;
import io.realm.RealmList;
public class PurchasedDeserializer implements JsonDeserializer<Purchases> {
@ -23,47 +20,21 @@ public class PurchasedDeserializer implements JsonDeserializer<Purchases> {
@Override
public Purchases deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject object = json.getAsJsonObject();
RealmList<Customization> customizations = new RealmList<>();
RealmList<OwnedCustomization> customizations = new RealmList<>();
Purchases purchases = new Purchases();
List<Customization> existingCustomizations;
try {
Realm realm = Realm.getDefaultInstance();
existingCustomizations = realm.copyFromRealm(realm.where(Customization.class).findAll());
realm.close();
} catch (RuntimeException e) {
//Tests don't have a database
existingCustomizations = new ArrayList<>();
}
for (Customization customization : existingCustomizations) {
if (object.has(customization.getType())) {
JsonObject nestedObject = object.get(customization.getType()).getAsJsonObject();
if (customization.getCategory() != null) {
if (nestedObject.has(customization.getCategory())) {
nestedObject = nestedObject.get(customization.getCategory()).getAsJsonObject();
} else {
continue;
}
}
if (nestedObject.has(customization.getIdentifier())) {
customizations.add(this.parseCustomization(customization, customization.getType(), customization.getCategory(), customization.getIdentifier(), nestedObject.get(customization.getIdentifier()).getAsBoolean()));
nestedObject.remove(customization.getIdentifier());
}
}
}
for (String type : Arrays.asList("background", "shirt", "skin")) {
if (!object.has(type)) {
continue;
}
for (Map.Entry<String, JsonElement> entry : object.get(type).getAsJsonObject().entrySet()) {
customizations.add(this.parseCustomization(null, type, null, entry.getKey(), entry.getValue().getAsBoolean()));
customizations.add(this.parseCustomization(type, null, entry.getKey(), entry.getValue().getAsBoolean()));
}
}
if (object.has("hair")) {
for (Map.Entry<String, JsonElement> categoryEntry : object.get("hair").getAsJsonObject().entrySet()) {
for (Map.Entry<String, JsonElement> entry : categoryEntry.getValue().getAsJsonObject().entrySet()) {
customizations.add(this.parseCustomization(null, "hair", categoryEntry.getKey(), entry.getKey(), entry.getValue().getAsBoolean()));
customizations.add(this.parseCustomization("hair", categoryEntry.getKey(), entry.getKey(), entry.getValue().getAsBoolean()));
}
}
}
@ -74,15 +45,12 @@ public class PurchasedDeserializer implements JsonDeserializer<Purchases> {
return purchases;
}
private Customization parseCustomization(Customization existingCustomizaion, String type, String category, String key, boolean wasPurchased) {
Customization customization = existingCustomizaion;
if (customization == null) {
customization = new Customization();
customization.setIdentifier(key);
customization.setType(type);
if (category != null) {
customization.setCategory(category);
}
private OwnedCustomization parseCustomization(String type, String category, String key, boolean wasPurchased) {
OwnedCustomization customization = new OwnedCustomization();
customization.setKey(key);
customization.setType(type);
if (category != null) {
customization.setCategory(category);
}
customization.setPurchased(wasPurchased);