diff --git a/Habitica/res/drawable-hdpi/difficulty_empty.png b/Habitica/res/drawable-hdpi/difficulty_empty.png new file mode 100644 index 000000000..fa9f8ad51 Binary files /dev/null and b/Habitica/res/drawable-hdpi/difficulty_empty.png differ diff --git a/Habitica/res/drawable-hdpi/difficulty_full.png b/Habitica/res/drawable-hdpi/difficulty_full.png new file mode 100644 index 000000000..b915063aa Binary files /dev/null and b/Habitica/res/drawable-hdpi/difficulty_full.png differ diff --git a/Habitica/res/drawable-mdpi/difficulty_empty.png b/Habitica/res/drawable-mdpi/difficulty_empty.png new file mode 100644 index 000000000..a635ab434 Binary files /dev/null and b/Habitica/res/drawable-mdpi/difficulty_empty.png differ diff --git a/Habitica/res/drawable-mdpi/difficulty_full.png b/Habitica/res/drawable-mdpi/difficulty_full.png new file mode 100644 index 000000000..21fa89a3a Binary files /dev/null and b/Habitica/res/drawable-mdpi/difficulty_full.png differ diff --git a/Habitica/res/drawable-xhdpi/difficulty_empty.png b/Habitica/res/drawable-xhdpi/difficulty_empty.png new file mode 100644 index 000000000..32c1c6bde Binary files /dev/null and b/Habitica/res/drawable-xhdpi/difficulty_empty.png differ diff --git a/Habitica/res/drawable-xhdpi/difficulty_full.png b/Habitica/res/drawable-xhdpi/difficulty_full.png new file mode 100644 index 000000000..d8a1571ed Binary files /dev/null and b/Habitica/res/drawable-xhdpi/difficulty_full.png differ diff --git a/Habitica/res/drawable-xxhdpi/difficulty_empty.png b/Habitica/res/drawable-xxhdpi/difficulty_empty.png new file mode 100644 index 000000000..ab64a87fb Binary files /dev/null and b/Habitica/res/drawable-xxhdpi/difficulty_empty.png differ diff --git a/Habitica/res/drawable-xxhdpi/difficulty_full.png b/Habitica/res/drawable-xxhdpi/difficulty_full.png new file mode 100644 index 000000000..f7804f3ae Binary files /dev/null and b/Habitica/res/drawable-xxhdpi/difficulty_full.png differ diff --git a/Habitica/res/drawable/boss_health_bg.xml b/Habitica/res/drawable/boss_health_bg.xml new file mode 100644 index 000000000..0a424f4dd --- /dev/null +++ b/Habitica/res/drawable/boss_health_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Habitica/res/drawable/quest_collection_bg.xml b/Habitica/res/drawable/quest_collection_bg.xml new file mode 100644 index 000000000..c2c89c65d --- /dev/null +++ b/Habitica/res/drawable/quest_collection_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Habitica/res/drawable/quest_difficulty_bg.xml b/Habitica/res/drawable/quest_difficulty_bg.xml new file mode 100644 index 000000000..96c52e317 --- /dev/null +++ b/Habitica/res/drawable/quest_difficulty_bg.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Habitica/res/drawable/quest_difficulty_rating.xml b/Habitica/res/drawable/quest_difficulty_rating.xml new file mode 100644 index 000000000..e9168c5c8 --- /dev/null +++ b/Habitica/res/drawable/quest_difficulty_rating.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Habitica/res/layout/avatar_with_bars.xml b/Habitica/res/layout/avatar_with_bars.xml index 1ab5b5c34..3f04866b8 100644 --- a/Habitica/res/layout/avatar_with_bars.xml +++ b/Habitica/res/layout/avatar_with_bars.xml @@ -71,7 +71,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="6dp" - android:paddingBottom="6dp"> + android:paddingBottom="6dp" + android:gravity="center_vertical"> + android:layout_height="wrap_content"/> \ No newline at end of file diff --git a/Habitica/res/layout/currency_view.xml b/Habitica/res/layout/currency_view.xml index 555eec97d..b467023a1 100644 --- a/Habitica/res/layout/currency_view.xml +++ b/Habitica/res/layout/currency_view.xml @@ -15,6 +15,8 @@ android:textColor="@color/textColorSecondaryDark" style="@style/CurrencyTextView" android:visibility="gone" + tools:visibility="visible" + tools:text="2" /> \ No newline at end of file diff --git a/Habitica/res/layout/dialog_purchase_content_item.xml b/Habitica/res/layout/dialog_purchase_content_item.xml new file mode 100644 index 000000000..ae2e77e45 --- /dev/null +++ b/Habitica/res/layout/dialog_purchase_content_item.xml @@ -0,0 +1,34 @@ + + + + + + + \ No newline at end of file diff --git a/Habitica/res/layout/dialog_purchase_content_quest.xml b/Habitica/res/layout/dialog_purchase_content_quest.xml new file mode 100644 index 000000000..e4e8c48a3 --- /dev/null +++ b/Habitica/res/layout/dialog_purchase_content_quest.xml @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Habitica/res/layout/dialog_purchase_shopitem.xml b/Habitica/res/layout/dialog_purchase_shopitem.xml index 9b6d2bd40..dc6fa1d94 100644 --- a/Habitica/res/layout/dialog_purchase_shopitem.xml +++ b/Habitica/res/layout/dialog_purchase_shopitem.xml @@ -37,11 +37,16 @@ android:background="@color/brand_300" android:textColor="@color/white" tools:text="Available until May 6"/> - + + + + android:layout_centerVertical="true" + android:src="@drawable/pin" + android:background="@color/transparent"/> + + + + + + \ No newline at end of file diff --git a/Habitica/res/layout/widget_avatar_stats.xml b/Habitica/res/layout/widget_avatar_stats.xml index c6622d3af..5d194b75d 100644 --- a/Habitica/res/layout/widget_avatar_stats.xml +++ b/Habitica/res/layout/widget_avatar_stats.xml @@ -201,7 +201,8 @@ android:id="@+id/detail_info_view" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingTop="@dimen/bar_padding_small"> + android:paddingTop="@dimen/bar_padding_small" + android:gravity="center_vertical"> #0b000000 #16000000 #33000000 + #89000000 #F6F4F8 #ddc994 @@ -147,4 +148,5 @@ #EC720E #313131 #ee9109 + #4cfedead diff --git a/Habitica/res/values/dimens.xml b/Habitica/res/values/dimens.xml index cfda63fb4..748a2d602 100644 --- a/Habitica/res/values/dimens.xml +++ b/Habitica/res/values/dimens.xml @@ -114,4 +114,5 @@ 68dp 186dp 24dp + 24dp diff --git a/Habitica/res/values/strings.constants.xml b/Habitica/res/values/strings.constants.xml index dd206e517..f0165b571 100644 --- a/Habitica/res/values/strings.constants.xml +++ b/Habitica/res/values/strings.constants.xml @@ -25,4 +25,5 @@ Ian Leslie Time Travelers + diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml index 444683d53..d7d268beb 100644 --- a/Habitica/res/values/strings.xml +++ b/Habitica/res/values/strings.xml @@ -629,4 +629,15 @@ b Your balance: Available until %s + Monthly Gems: %1$d/%2$d Remaining + Monthly Gems: %d Remaining + Health + Collect + Rage Meter + Boss Quest + Collection Quest + %1$s x%2$d + %d Experience points + %d Gold + Quest Owner Rewards diff --git a/Habitica/res/values/styles.xml b/Habitica/res/values/styles.xml index fe0178285..6aefaed42 100644 --- a/Habitica/res/values/styles.xml +++ b/Habitica/res/values/styles.xml @@ -399,4 +399,10 @@ 4dp center + + \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java index 7cbea6075..04da80254 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java @@ -41,6 +41,7 @@ import com.habitrpg.android.habitica.models.inventory.Pet; import com.habitrpg.android.habitica.models.inventory.Quest; import com.habitrpg.android.habitica.models.inventory.QuestCollect; import com.habitrpg.android.habitica.models.inventory.QuestContent; +import com.habitrpg.android.habitica.models.inventory.QuestDropItem; import com.habitrpg.android.habitica.models.members.Member; import com.habitrpg.android.habitica.models.responses.BuyResponse; import com.habitrpg.android.habitica.models.responses.ErrorResponse; @@ -84,6 +85,7 @@ import com.habitrpg.android.habitica.utils.PetMapDeserializer; import com.habitrpg.android.habitica.utils.PurchasedDeserializer; import com.habitrpg.android.habitica.utils.QuestCollectDeserializer; import com.habitrpg.android.habitica.utils.QuestDeserializer; +import com.habitrpg.android.habitica.utils.QuestDropItemsListSerialization; import com.habitrpg.android.habitica.utils.QuestListDeserializer; import com.habitrpg.android.habitica.utils.SkillDeserializer; import com.habitrpg.android.habitica.utils.TaskListDeserializer; @@ -226,6 +228,7 @@ public class ApiClientImpl implements Action1, ApiClient { Type questCollectListType = new TypeToken>() {}.getType(); Type chatMessageListType = new TypeToken>() {}.getType(); Type challengeListType = new TypeToken>() {}.getType(); + Type questDropItemListType = new TypeToken>() {}.getType(); //Exclusion strategy needed for DBFlow https://github.com/Raizlabs/DBFlow/issues/121 Gson gson = new GsonBuilder() @@ -258,6 +261,7 @@ public class ApiClientImpl implements Action1, ApiClient { .registerTypeAdapter(questCollectListType, new QuestCollectDeserializer()) .registerTypeAdapter(chatMessageListType, new ChatMessageListDeserializer()) .registerTypeAdapter(challengeListType, new ChallengeListDeserializer()) + .registerTypeAdapter(questDropItemListType, new QuestDropItemsListSerialization()) .registerTypeAdapter(Quest.class, new QuestDeserializer()) .registerTypeAdapter(Member.class, new MemberSerialization()) .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/NotifyUserUseCase.java b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/NotifyUserUseCase.java index 24a9dde3b..a36f2d105 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/NotifyUserUseCase.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/NotifyUserUseCase.java @@ -98,9 +98,9 @@ public class NotifyUserUseCase extends UseCase 0) { - text = " + "+String.valueOf(Math.abs(round(value, 2)); + text = " + "+String.valueOf(Math.abs(round(value, 2))); } else { - text = " - "+String.valueOf(Math.abs(round(value, 2)); + text = " - "+String.valueOf(Math.abs(round(value, 2))); } textView.setText(text); textView.setGravity(Gravity.CENTER_VERTICAL); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestBoss.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestBoss.java index d0c532be1..e149151b7 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestBoss.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestBoss.java @@ -8,34 +8,21 @@ import io.realm.annotations.PrimaryKey; public class QuestBoss extends RealmObject { @PrimaryKey - public String key; + private String key; public String name; - public double hp; - public double str; - public double def; + public int hp; + public float str; - /* Boss Columns */ - - public String rage_title; - public String rage_description; - public double rage_value; - public String rage_tavern; - public String rage_stables; - public String rage_market; - @Ignore public QuestBossRage rage; - public class QuestBossRage { - public String title; + public boolean hasRage() { + return rage != null && rage.value != 0; + } - public String description; - - public double value; - - public String tavern; - - public String stables; - - public String market; + public void setKey(String key) { + this.key = key; + if (rage != null) { + rage.key = key; + } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestBossRage.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestBossRage.java new file mode 100644 index 000000000..2ab99fa42 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestBossRage.java @@ -0,0 +1,26 @@ +package com.habitrpg.android.habitica.models.inventory; + +import io.realm.RealmObject; +import io.realm.annotations.PrimaryKey; + +public class QuestBossRage extends RealmObject { + + @PrimaryKey + public String key; + + public String title; + + public String description; + + public double value; + + public String tavern; + + public String stables; + + public String market; + + public QuestBossRage() { + super(); + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestContent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestContent.java index c004346f2..7e93a241f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestContent.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestContent.java @@ -12,11 +12,12 @@ public class QuestContent extends RealmObject implements Item { String key; String text, notes; int value, owned; - public String previous; - public int lvl; - public boolean canBuy; - public String category; - public QuestBoss boss; + private String previous; + private int lvl; + private boolean canBuy; + private String category; + private QuestBoss boss; + private QuestDrops drop; RealmList collect; @@ -58,6 +59,9 @@ public class QuestContent extends RealmObject implements Item { public void setBoss(QuestBoss boss) { this.boss = boss; + if (boss != null) { + boss.setKey(key); + } } public RealmList getCollect() { @@ -127,4 +131,19 @@ public class QuestContent extends RealmObject implements Item { } return null; } + + public QuestDrops getDrop() { + return drop; + } + + public void setDrop(QuestDrops drop) { + this.drop = drop; + if (drop != null) { + drop.setKey(key); + } + } + + public boolean isBossQuest() { + return boss != null; + } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestDropItem.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestDropItem.java new file mode 100644 index 000000000..f50a5155f --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestDropItem.java @@ -0,0 +1,97 @@ +package com.habitrpg.android.habitica.models.inventory; + +import io.realm.RealmObject; +import io.realm.annotations.PrimaryKey; + +/** + * Created by phillip on 25.07.17. + */ + +public class QuestDropItem extends RealmObject { + + @PrimaryKey + private String combinedKey; + private String questKey; + private String key; + private String type; + private String text; + private boolean onlyOwner; + private int count; + + public QuestDropItem() { + super(); + } + + public String getCombinedKey() { + return combinedKey; + } + + public void setCombinedKey(String combinedKey) { + this.combinedKey = combinedKey; + } + + public String getQuestKey() { + return questKey; + } + + public void setQuestKey(String questKey) { + this.questKey = questKey; + combinedKey = questKey+key; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + combinedKey = questKey+key; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public String getImageName() { + if ("quests".equals(type)) { + return "inventory_quest_scroll_"+key; + } else if ("eggs".equals(type)) { + return "Pet_Egg_" + getKey(); + } else + if ("food".equals(type)) { + return "Pet_Food_" + getKey(); + } else + if ("hatchingPotions".equals(type)) { + return "Pet_HatchingPotion_" + getKey(); + } + return "shop_"+key; + } + + public boolean isOnlyOwner() { + return onlyOwner; + } + + public void setOnlyOwner(boolean onlyOwner) { + this.onlyOwner = onlyOwner; + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestDrops.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestDrops.java new file mode 100644 index 000000000..f76dc7c18 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/QuestDrops.java @@ -0,0 +1,52 @@ +package com.habitrpg.android.habitica.models.inventory; + +import io.realm.RealmList; +import io.realm.RealmObject; +import io.realm.annotations.PrimaryKey; + +/** + * Created by phillip on 25.07.17. + */ + +public class QuestDrops extends RealmObject { + + @PrimaryKey + private String key; + public int gp; + public int exp; + public String unlock; + private RealmList items; + + public QuestDrops() { + super(); + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + + if (items != null) { + for (QuestDropItem item : items) { + item.setQuestKey(key); + } + } + } + + + public RealmList getItems() { + return items; + } + + public void setItems(RealmList items) { + this.items = items; + + if (items != null) { + for (QuestDropItem item : items) { + item.setQuestKey(key); + } + } + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/Shop.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/Shop.java index c2675da3f..e0057070e 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/Shop.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/Shop.java @@ -1,5 +1,9 @@ package com.habitrpg.android.habitica.models.shops; +import android.content.Context; + +import com.habitrpg.android.habitica.R; + import java.util.List; public class Shop { @@ -54,4 +58,23 @@ public class Shop { public void setCategories(List categories) { this.categories = categories; } + + public int getNpcNameResource() { + switch (getIdentifier()) { + case "market": + return R.string.market_owner; + case "questShop": + return R.string.questShop_owner; + case "seasonalShop": + return R.string.seasonalShop_owner; + case "timetravelersShop": + return R.string.timetravelers_owner; + default: + return R.string.market_owner; + } + } + + public String getNpcName(Context context) { + return context.getString(getNpcNameResource()); + } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItem.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItem.java index 39d150f6c..7b33a6b6b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItem.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItem.java @@ -61,7 +61,11 @@ public class ShopItem { public String getImageName() { if (imageName != null) { - return imageName.replace("inventory_quest_scroll_locked", ""); + if (imageName.contains(" ")) { + return imageName.split(" ")[1]; + } else { + return imageName; + } } else { return "shop_" + key; } @@ -140,4 +144,20 @@ public class ShopItem { public boolean isLimited() { return limited; } + + public boolean isTypeItem() { + return "eggs".equals(purchaseType) || "hatchingPotions".equals(purchaseType) || "food".equals(purchaseType); + } + + public boolean isTypeQuest() { + return "quests".equals(purchaseType); + } + + public boolean isTypeGear() { + return false; + } + + public boolean isTypeAnimal() { + return "pets".equals(purchaseType) || "mounts".equals(purchaseType); + } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItemUnlockCondition.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItemUnlockCondition.java index 954e19e78..c409eaa3e 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItemUnlockCondition.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItemUnlockCondition.java @@ -12,7 +12,7 @@ public class ShopItemUnlockCondition { case "party invite": return R.string.party_invite; default: - return 0; + return R.string.empty; } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/SubscriptionPlan.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/SubscriptionPlan.java index 38165d910..442a18c2a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/SubscriptionPlan.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/SubscriptionPlan.java @@ -40,11 +40,15 @@ public class SubscriptionPlan extends RealmObject { return planId != null && (this.dateTerminated == null || this.dateTerminated.after(today)); } - public Integer numberOfGemsLeft() { + public int totalNumberOfGems() { if (customerId == null) { return 0; } - return 25 + consecutive.getGemCapExtra() - gemsBought; + return 25 + consecutive.getGemCapExtra(); + } + + public int numberOfGemsLeft() { + return totalNumberOfGems() - gemsBought; } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ShopRecyclerAdapter.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ShopRecyclerAdapter.java index cc0726b25..633333a34 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ShopRecyclerAdapter.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ShopRecyclerAdapter.java @@ -190,9 +190,14 @@ public class ShopRecyclerAdapter extends RecyclerView.Adapter 0); + boolean showHpBar = (quest.getBoss() != null && quest.getBoss().hp > 0); bossHpBar.setVisibility(showHpBar ? View.VISIBLE : View.GONE); if (showHpBar) { - bossHpBar.set(group.quest.getProgress().hp, quest.boss.hp); + bossHpBar.set(group.quest.getProgress().hp, quest.getBoss().hp); } - boolean showRageBar = (quest.boss != null && quest.boss.rage_value > 0); + boolean showRageBar = (quest.getBoss() != null && quest.getBoss().hasRage()); bossRageBar.setVisibility(showRageBar ? View.VISIBLE : View.GONE); if (showRageBar) { - bossHpBar.set(group.quest.getProgress().rage, quest.boss.rage_value); + bossHpBar.set(group.quest.getProgress().rage, quest.getBoss().rage.value); } if (group.quest.members == null) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/DataBindingUtils.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/DataBindingUtils.java index e186c4ba1..457fde68a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/DataBindingUtils.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/DataBindingUtils.java @@ -32,13 +32,6 @@ public class DataBindingUtils { } } - @BindingAdapter("bind:questImageName") - public static void loadQuestImage(SimpleDraweeView view, String imageName) { - if (view != null && view.getVisibility() == View.VISIBLE) { - view.setImageURI(Uri.parse("https://habitica-assets.s3.amazonaws.com/mobileApp/images/" + imageName + ".png")); - } - } - @BindingAdapter("bind:cardColor") public static void setCardColor(CardView cardView, int color) { if (color > 0) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.java index ba1debada..1841976c5 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.java @@ -1,15 +1,20 @@ package com.habitrpg.android.habitica.ui.views.shops; +import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.support.v4.content.ContextCompat; +import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.ScrollView; import android.widget.TextView; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.components.AppComponent; +import com.habitrpg.android.habitica.data.InventoryRepository; import com.habitrpg.android.habitica.data.UserRepository; import com.habitrpg.android.habitica.helpers.RxErrorHandler; import com.habitrpg.android.habitica.models.shops.ShopItem; @@ -24,15 +29,14 @@ import javax.inject.Inject; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; - -/** - * Created by phillip on 21.07.17. - */ +import rx.subscriptions.CompositeSubscription; public class PurchaseDialog extends AlertDialog { @Inject UserRepository userRepository; + @Inject + InventoryRepository inventoryRepository; @BindView(R.id.currencyView) CurrencyView currencyView; @@ -44,13 +48,24 @@ public class PurchaseDialog extends AlertDialog { ImageView currencyIconView; @BindView(R.id.buyButton) View buyButton; + @BindView(R.id.content_container) + ViewGroup contentContainer; + @BindView(R.id.scrollView) + ScrollView scrollView; + private ShopItem shopItem; + PurchaseDialogContent contentView; + + CompositeSubscription compositeSubscription; + public PurchaseDialog(Context context, AppComponent component, ShopItem item) { super(context); component.inject(this); + compositeSubscription = new CompositeSubscription(); + LayoutInflater inflater = LayoutInflater.from(context); View view = inflater.inflate(R.layout.dialog_purchase_shopitem, null); ButterKnife.bind(this, view); @@ -58,18 +73,34 @@ public class PurchaseDialog extends AlertDialog { setShopItem(item); - userRepository.getUser().subscribe(this::setUser, RxErrorHandler.handleEmptyError()); + compositeSubscription.add(userRepository.getUser().subscribe(this::setUser, RxErrorHandler.handleEmptyError())); } private void setUser(User user) { currencyView.setGold(user.getStats().getGp()); currencyView.setGems(user.getGemCount()); currencyView.setHourglasses(user.getHourglassCount()); + + if ("gems".equals(shopItem.purchaseType)) { + int gemsLeft = shopItem.limitedNumberLeft != null ? shopItem.limitedNumberLeft : 0; + int maxGems = user.getPurchased().getPlan().totalNumberOfGems(); + if (maxGems > 0) { + limitedTextView.setText(getContext().getString(R.string.gems_left_max, gemsLeft, maxGems)); + } else { + limitedTextView.setText(getContext().getString(R.string.gems_left_nomax, gemsLeft)); + } + limitedTextView.setVisibility(View.VISIBLE); + limitedTextView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.good_10)); + } } @Override public void dismiss() { userRepository.close(); + inventoryRepository.close(); + if (compositeSubscription != null && !compositeSubscription.isUnsubscribed()) { + compositeSubscription.unsubscribe(); + } super.dismiss(); } @@ -86,11 +117,14 @@ public class PurchaseDialog extends AlertDialog { } else if (item.getCurrency().equals("gems")) { currencyIconView.setImageResource(R.drawable.currency_gem); priceLabel.setTextColor(ContextCompat.getColor(getContext(), R.color.good_10)); + } else if (item.getCurrency().equals("hourglasses")) { + currencyIconView.setImageResource(R.drawable.currency_hourglass); + priceLabel.setTextColor(ContextCompat.getColor(getContext(), R.color.brand_300)); } else { - buyButton.setVisibility(View.GONE); + setBuyButtonEnabled(false); } } else { - buyButton.setVisibility(View.GONE); + setBuyButtonEnabled(false); } if (item.isLimited()) { @@ -106,10 +140,55 @@ public class PurchaseDialog extends AlertDialog { } else { currencyIconView.setAlpha(1.0f); } + + if (shopItem.isTypeItem()) { + contentView = new PurchaseDialogItemContent(getContext()); + } else if (shopItem.isTypeQuest()) { + contentView = new PurchaseDialogQuestContent(getContext()); + inventoryRepository.getQuestContent(item.getKey()).first().subscribe(((PurchaseDialogQuestContent)contentView)::setQuestContent, RxErrorHandler.handleEmptyError()); + } else if ("gems".equals(shopItem.purchaseType)) { + contentView = new PurchaseDialogGemsContent(getContext()); + } else { + contentView = new PurchaseDialogBaseContent(getContext()); + } + contentView.setItem(shopItem); + contentContainer.addView(contentView); + + + setScrollviewSize(); } + private void setScrollviewSize() { + scrollView.post(() -> { + if (getWindow() != null) { + int height = scrollView.getChildAt(0).getHeight(); + DisplayMetrics displayMetrics = new DisplayMetrics(); + getWindow().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); + int screenHeight = displayMetrics.heightPixels; + int spaceRequired = (int) (displayMetrics.density * 160); + + if (height > screenHeight-spaceRequired) { + ViewGroup.LayoutParams myScrollViewParams = scrollView.getLayoutParams(); + myScrollViewParams.height = screenHeight-spaceRequired; + scrollView.setLayoutParams(myScrollViewParams); + + } + } + }); + + } + + @OnClick(R.id.closeButton) - public void onCloseClicked() { + void onCloseClicked() { dismiss(); } + + public void setBuyButtonEnabled(boolean enabled) { + if (enabled) { + buyButton.setAlpha(0.5f); + } else{ + buyButton.setAlpha(1.0f); + } + } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogBaseContent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogBaseContent.java new file mode 100644 index 000000000..b0614b190 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogBaseContent.java @@ -0,0 +1,24 @@ +package com.habitrpg.android.habitica.ui.views.shops; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.AttributeSet; + +import com.habitrpg.android.habitica.R; + +public class PurchaseDialogBaseContent extends PurchaseDialogContent { + + public PurchaseDialogBaseContent(Context context) { + super(context); + } + + public PurchaseDialogBaseContent(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected int getViewId() { + return R.layout.dialog_purchase_content_item; + } + +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogContent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogContent.java new file mode 100644 index 000000000..ca62add7d --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogContent.java @@ -0,0 +1,52 @@ +package com.habitrpg.android.habitica.ui.views.shops; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.Gravity; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.habitrpg.android.habitica.R; +import com.habitrpg.android.habitica.models.inventory.QuestContent; +import com.habitrpg.android.habitica.models.shops.ShopItem; +import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public abstract class PurchaseDialogContent extends LinearLayout { + + @BindView(R.id.imageView) + SimpleDraweeView imageView; + @BindView(R.id.titleTextView) + TextView titleTextView; + + public PurchaseDialogContent(Context context) { + super(context); + setupView(); + } + + public PurchaseDialogContent(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + setupView(); + } + + private void setupView() { + setOrientation(LinearLayout.VERTICAL); + setGravity(Gravity.CENTER_HORIZONTAL); + + inflate(getContext(), getViewId(), this); + ButterKnife.bind(this, this); + } + + protected abstract int getViewId(); + + + public void setItem(ShopItem item) { + DataBindingUtils.loadImage(imageView, item.getImageName()); + titleTextView.setText(item.getText()); + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogGemsContent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogGemsContent.java new file mode 100644 index 000000000..d8d78b375 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogGemsContent.java @@ -0,0 +1,36 @@ +package com.habitrpg.android.habitica.ui.views.shops; + +import android.content.Context; +import android.widget.TextView; + +import com.habitrpg.android.habitica.R; +import com.habitrpg.android.habitica.models.shops.ShopItem; + +import butterknife.BindView; + +/** + * Created by phillip on 25.07.17. + */ + +class PurchaseDialogGemsContent extends PurchaseDialogContent { + + @BindView(R.id.notesTextView) + TextView notesTextView; + + public PurchaseDialogGemsContent(Context context) { + super(context); + } + + @Override + protected int getViewId() { + return R.layout.dialog_purchase_content_item; + } + + + @Override + public void setItem(ShopItem item) { + super.setItem(item); + + notesTextView.setText(item.getNotes()); + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogItemContent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogItemContent.java new file mode 100644 index 000000000..66620cfad --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogItemContent.java @@ -0,0 +1,37 @@ +package com.habitrpg.android.habitica.ui.views.shops; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.widget.TextView; + +import com.habitrpg.android.habitica.R; +import com.habitrpg.android.habitica.models.shops.ShopItem; + +import butterknife.BindView; + +public class PurchaseDialogItemContent extends PurchaseDialogContent { + + @BindView(R.id.notesTextView) + TextView notesTextView; + + public PurchaseDialogItemContent(Context context) { + super(context); + } + + public PurchaseDialogItemContent(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected int getViewId() { + return R.layout.dialog_purchase_content_item; + } + + @Override + public void setItem(ShopItem item) { + super.setItem(item); + + notesTextView.setText(item.getNotes()); + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogQuestContent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogQuestContent.java new file mode 100644 index 000000000..3fbe381b0 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogQuestContent.java @@ -0,0 +1,150 @@ +package com.habitrpg.android.habitica.ui.views.shops; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.Layout; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RatingBar; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.habitrpg.android.habitica.R; +import com.habitrpg.android.habitica.models.inventory.QuestCollect; +import com.habitrpg.android.habitica.models.inventory.QuestContent; +import com.habitrpg.android.habitica.models.inventory.QuestDropItem; +import com.habitrpg.android.habitica.models.shops.ShopItem; +import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; + +/** + * Created by phillip on 24.07.17. + */ + +public class PurchaseDialogQuestContent extends PurchaseDialogContent { + + @BindView(R.id.questDetailView) + View questDetailView; + @BindView(R.id.questTypeTextView) + TextView questTypeTextView; + @BindView(R.id.boss_health_view) + View bossHealthView; + @BindView(R.id.boss_health_text) + TextView bossHealthTextView; + @BindView(R.id.quest_collect_view) + View questCollectView; + @BindView(R.id.quest_collect_text) + TextView questCollectTextView; + @BindView(R.id.quest_difficulty_view) + RatingBar questDifficultyView; + @BindView(R.id.rage_meter_view) + View rageMeterView; + @BindView(R.id.rewardsList) + ViewGroup rewardsList; + @BindView(R.id.ownerRewardsTitle) + View ownerRewardsTitle; + @BindView(R.id.ownerRewardsList) + ViewGroup ownerRewardsList; + + public PurchaseDialogQuestContent(Context context) { + super(context); + } + + public PurchaseDialogQuestContent(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected int getViewId() { + return R.layout.dialog_purchase_content_quest; + } + + @Override + public void setItem(ShopItem item) { + super.setItem(item); + } + + public void setQuestContent(QuestContent questContent) { + + if (questContent.isBossQuest()) { + questTypeTextView.setText(R.string.boss_quest); + questCollectView.setVisibility(View.GONE); + bossHealthTextView.setText(String.valueOf(questContent.getBoss().hp)); + if (questContent.getBoss().hasRage()) { + rageMeterView.setVisibility(View.VISIBLE); + } + questDifficultyView.setRating(questContent.getBoss().str); + } else{ + questTypeTextView.setText(R.string.collection_quest); + List collectionList = new ArrayList<>(); + for (QuestCollect collect : questContent.getCollect()) { + collectionList.add(collect.count + " " + collect.text); + } + questCollectTextView.setText(TextUtils.join(", ", collectionList)); + + bossHealthView.setVisibility(View.GONE); + + questDifficultyView.setRating(1); + } + + questDetailView.setVisibility(View.VISIBLE); + + LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + if (questContent.getDrop().getItems() != null) { + for (QuestDropItem item : questContent.getDrop().getItems()) { + if (!item.isOnlyOwner()) { + addRewardsRow(inflater, item, rewardsList); + } + } + + boolean hasOwnerRewards = false; + for (QuestDropItem item : questContent.getDrop().getItems()) { + if (item.isOnlyOwner()) { + addRewardsRow(inflater, item, ownerRewardsList); + hasOwnerRewards = true; + } + } + if (!hasOwnerRewards) { + ownerRewardsTitle.setVisibility(View.GONE); + ownerRewardsList.setVisibility(View.GONE); + } + + if (questContent.getDrop().exp > 0) { + ViewGroup view = (ViewGroup) inflater.inflate(R.layout.row_quest_reward, rewardsList, false); + SimpleDraweeView imageView = (SimpleDraweeView) view.findViewById(R.id.imageView); + TextView titleTextView = (TextView) view.findViewById(R.id.titleTextView); + titleTextView.setText(getContext().getString(R.string.experience_reward, questContent.getDrop().exp)); + rewardsList.addView(view); + } + + if (questContent.getDrop().gp > 0) { + ViewGroup view = (ViewGroup) inflater.inflate(R.layout.row_quest_reward, rewardsList, false); + SimpleDraweeView imageView = (SimpleDraweeView) view.findViewById(R.id.imageView); + TextView titleTextView = (TextView) view.findViewById(R.id.titleTextView); + titleTextView.setText(getContext().getString(R.string.gold_reward, questContent.getDrop().gp)); + rewardsList.addView(view); + } + } + } + + private void addRewardsRow(LayoutInflater inflater, QuestDropItem item, ViewGroup containerView) { + ViewGroup view = (ViewGroup) inflater.inflate(R.layout.row_quest_reward, containerView, false); + SimpleDraweeView imageView = (SimpleDraweeView) view.findViewById(R.id.imageView); + TextView titleTextView = (TextView) view.findViewById(R.id.titleTextView); + DataBindingUtils.loadImage(imageView, item.getImageName()); + if (item.getCount() > 1) { + titleTextView.setText(getContext().getString(R.string.quest_reward_count, item.getText(), item.getCount())); + } else { + titleTextView.setText(item.getText()); + } + containerView.addView(view); + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestProgressView.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestProgressView.java index 570f1df9b..cea32ee8d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestProgressView.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestProgressView.java @@ -50,10 +50,10 @@ public class QuestProgressView extends LinearLayout { public void setData(QuestContent quest, QuestProgress progress) { collectionContainer.removeAllViews(); - if (quest.boss != null) { - bossNameView.setText(quest.boss.name); + if (quest.isBossQuest()) { + bossNameView.setText(quest.getBoss().name); if (progress != null) { - bossHealthView.set(progress.hp, quest.boss.hp); + bossHealthView.set(progress.hp, quest.getBoss().hp); } bossNameView.setVisibility(View.VISIBLE); bossHealthView.setVisibility(View.VISIBLE); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/QuestDropItemsListSerialization.java b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/QuestDropItemsListSerialization.java new file mode 100644 index 000000000..d1f808a0c --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/QuestDropItemsListSerialization.java @@ -0,0 +1,43 @@ +package com.habitrpg.android.habitica.utils; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.habitrpg.android.habitica.models.inventory.QuestDropItem; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +import io.realm.RealmList; + +/** + * Created by phillip on 25.07.17. + */ + +public class QuestDropItemsListSerialization implements JsonDeserializer> { + @Override + public RealmList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + RealmList items = new RealmList<>(); + List keys = new ArrayList<>(); + + for (JsonElement e : json.getAsJsonArray()) { + QuestDropItem item = context.deserialize(e, QuestDropItem.class); + if (keys.contains(item.getKey())) { + for (QuestDropItem existingItem : items) { + if (existingItem.getKey().equals(item.getKey())) { + existingItem.setCount(existingItem.getCount()+1); + } + } + } else { + item.setCount(1); + items.add(item); + keys.add(item.getKey()); + } + } + + + return items; + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/QuestListDeserializer.java b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/QuestListDeserializer.java index 493c075ae..1f373e909 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/QuestListDeserializer.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/QuestListDeserializer.java @@ -37,9 +37,7 @@ public class QuestListDeserializer implements JsonDeserializer