add purchase dialog for quests

This commit is contained in:
Phillip Thelen 2017-07-25 18:27:00 +02:00
parent d7ea9e9c6b
commit aae43575e6
49 changed files with 1019 additions and 84 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 B

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/worse_50" />
<corners android:topLeftRadius="4dp" android:topRightRadius="4dp" />
</shape>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/good_50" />
<corners android:topLeftRadius="4dp" android:topRightRadius="4dp" />
</shape>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/gray_700" />
<corners android:bottomLeftRadius="4dp" android:bottomRightRadius="4dp" />
</shape>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background" android:drawable="@drawable/difficulty_empty" />
<item android:id="@android:id/secondaryProgress" android:drawable="@drawable/difficulty_empty" />
<item android:id="@android:id/progress" android:drawable="@drawable/difficulty_full" />
</layer-list>

View file

@ -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">
<TextView
android:id="@+id/lvl_tv"
android:layout_width="wrap_content"
@ -90,6 +91,6 @@
<com.habitrpg.android.habitica.ui.views.CurrencyView
android:id="@+id/currencyView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>

View file

@ -15,6 +15,8 @@
android:textColor="@color/textColorSecondaryDark"
style="@style/CurrencyTextView"
android:visibility="gone"
tools:visibility="visible"
tools:text="2"
/>
<TextView
android:id="@+id/gemTextView"
@ -25,6 +27,8 @@
android:textColor="@color/textColorSecondaryDark"
style="@style/CurrencyTextView"
android:visibility="gone"
tools:visibility="visible"
tools:text="22"
/>
<TextView
@ -35,5 +39,6 @@
android:layout_height="wrap_content"
android:textColor="@color/textColorSecondaryDark"
style="@style/CurrencyTextView"
tools:text="4.2k"
/>
</merge>

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/shopitem_dialog_content_inset"
android:paddingRight="@dimen/shopitem_dialog_content_inset"
android:gravity="center_horizontal"
tools:parentTag="LinearLayout"
tools:orientation="vertical">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/imageView"
android:layout_width="@dimen/shopitem_image_size"
android:layout_height="@dimen/shopitem_image_size" />
<TextView
android:id="@id/titleTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Headline"
tools:text="This is the Title"
android:gravity="center"
android:layout_marginTop="14dp"
android:layout_marginBottom="4dp"/>
<TextView
android:id="@id/notesTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Body2"
android:textColor="@color/black_50_alpha"
tools:text="These are the notes"
android:gravity="center"/>
</merge>

View file

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/shopitem_dialog_content_inset"
android:paddingRight="@dimen/shopitem_dialog_content_inset"
android:gravity="center_horizontal"
tools:parentTag="LinearLayout"
tools:orientation="vertical">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/imageView"
android:layout_width="@dimen/shopitem_image_size"
android:layout_height="@dimen/shopitem_image_size" />
<TextView
android:id="@id/titleTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Headline"
tools:text="This is the Title"
android:gravity="center"
android:layout_marginTop="14dp"
android:layout_marginBottom="4dp"/>
<TextView
android:id="@id/notesTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Body2"
android:textColor="@color/black_50_alpha"
tools:text="These are the notes"
android:gravity="center"/>
<TextView
android:id="@+id/questTypeTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center_horizontal"
android:layout_marginBottom="4dp"
style="@style/Body1"
/>
<TableLayout
android:id="@+id/questDetailView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
tools:visibility="visible"
android:shrinkColumns="1"
android:stretchColumns="1">
<TableRow
android:id="@+id/boss_health_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/boss_health_bg"
android:gravity="center_vertical">
<TextView
android:text="@string/health"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Body2"
android:textColor="@color/white"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/boss_health_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/snack_heart_red"
android:textColor="@color/white"
tools:text="1000"
android:gravity="center_vertical"
style="@style/Body2"
/>
</TableRow>
<TableRow
android:id="@+id/quest_collect_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/quest_collection_bg"
android:gravity="center_vertical">
<TextView
android:text="@string/collect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Body2"
android:textColor="@color/white"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"/>
<TextView
android:id="@+id/quest_collect_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="List of items"
android:textColor="@color/white"
style="@style/Body2"
/>
</TableRow>
<TableRow
android:id="@+id/difficulty_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/quest_difficulty_bg"
android:gravity="center_vertical">
<TextView
android:text="@string/difficulty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Body2"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RatingBar
android:id="@+id/quest_difficulty_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:rating="2.5"
style="@style/QuestRatingBar"
android:numStars="4"
android:stepSize="0.5"
android:isIndicator="true"
/>
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="@+id/rage_meter_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/pill_bg"
android:gravity="right"
android:paddingBottom="2dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="2dp"
android:text="@string/rage_meter"
android:visibility="gone"
tools:visibility="visible"
android:layout_marginRight="8dp"/>
</LinearLayout>
</TableRow>
</TableLayout>
<TextView
android:text="@string/rewards"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="4dp"
android:gravity="center_horizontal"
/>
<LinearLayout
android:id="@+id/rewardsList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
<TextView
android:id="@+id/ownerRewardsTitle"
android:text="@string/quest_owner_rewards"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="4dp"
android:gravity="center_horizontal"
/>
<LinearLayout
android:id="@+id/ownerRewardsList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</merge>

View file

@ -37,11 +37,16 @@
android:background="@color/brand_300"
android:textColor="@color/white"
tools:text="Available until May 6"/>
<FrameLayout
android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="100dp"/>
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:id="@+id/content_container"
android:padding="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
@ -58,7 +63,9 @@
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"/>
android:layout_centerVertical="true"
android:src="@drawable/pin"
android:background="@color/transparent"/>
<LinearLayout
android:id="@+id/buyButton"
android:layout_width="wrap_content"

View file

@ -273,7 +273,7 @@
android:layout_width="@dimen/quest_image_width"
android:layout_height="@dimen/quest_image_height"
android:layout_marginBottom="8dp"
bind:questImageName='@{"quest_"+ quest.key}'
bind:imageName='@{"quest_"+ quest.key}'
/>
<LinearLayout

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/layout_rounded_bg_gray_700"
android:gravity="center_vertical"
android:layout_marginBottom="4dp">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/imageView"
android:layout_width="@dimen/shopitem_image_size"
android:layout_height="@dimen/shopitem_image_size"
android:layout_marginRight="8dp"/>
<TextView
android:id="@+id/titleTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"/>
</LinearLayout>

View file

@ -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">
<TextView
android:id="@+id/lvl_tv"
android:layout_width="wrap_content"

View file

@ -130,6 +130,7 @@
<color name="black_5_alpha">#0b000000</color>
<color name="black_10_alpha">#16000000</color>
<color name="black_20_alpha">#33000000</color>
<color name="black_50_alpha">#89000000</color>
<color name="light_gray_bg">#F6F4F8</color>
<color name="skin_ddc994">#ddc994</color>
@ -147,4 +148,5 @@
<color name="hair_red">#EC720E</color>
<color name="hair_black">#313131</color>
<color name="gold">#ee9109</color>
<color name="reward_buy_button_bg">#4cfedead</color>
</resources>

View file

@ -114,4 +114,5 @@
<dimen name="shopitem_image_size">68dp</dimen>
<dimen name="shop_scene_height">186dp</dimen>
<dimen name="currency_icon_size">24dp</dimen>
<dimen name="shopitem_dialog_content_inset">24dp</dimen>
</resources>

View file

@ -25,4 +25,5 @@
<string name="questShop_owner" translatable="false">Ian</string>
<string name="seasonalShop_owner" translatable="false">Leslie</string>
<string name="timetravelers_owner" translatable="false">Time Travelers</string>
<string name="empty" translatable="false"> </string>
</resources>

View file

@ -629,4 +629,15 @@
<string name="billion_abbrev">b</string>
<string name="your_balance">Your balance:</string>
<string name="available_until" formatted="false">Available until %s</string>
<string name="gems_left_max" formatted="false">Monthly Gems: %1$d/%2$d Remaining</string>
<string name="gems_left_nomax" formatted="false">Monthly Gems: %d Remaining</string>
<string name="health">Health</string>
<string name="collect">Collect</string>
<string name="rage_meter">Rage Meter</string>
<string name="boss_quest">Boss Quest</string>
<string name="collection_quest">Collection Quest</string>
<string name="quest_reward_count" formatted="false">%1$s x%2$d</string>
<string name="experience_reward" formatted="false">%d Experience points</string>
<string name="gold_reward" formatted="false">%d Gold</string>
<string name="quest_owner_rewards">Quest Owner Rewards</string>
</resources>

View file

@ -399,4 +399,10 @@
<item name="android:drawablePadding">4dp</item>
<item name="android:gravity">center</item>
</style>
<style name="QuestRatingBar" parent="@android:style/Widget.RatingBar">
<item name="android:progressDrawable">@drawable/quest_difficulty_rating</item>
<item name="android:minHeight">12dip</item>
<item name="android:maxHeight">12dip</item>
</style>
</resources>

View file

@ -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<Throwable>, ApiClient {
Type questCollectListType = new TypeToken<RealmList<QuestCollect>>() {}.getType();
Type chatMessageListType = new TypeToken<RealmList<ChatMessage>>() {}.getType();
Type challengeListType = new TypeToken<List<Challenge>>() {}.getType();
Type questDropItemListType = new TypeToken<RealmList<QuestDropItem>>() {}.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<Throwable>, 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'")

View file

@ -98,9 +98,9 @@ public class NotifyUserUseCase extends UseCase<NotifyUserUseCase.RequestValues,
textView.setCompoundDrawablesWithIntrinsicBounds(icon, 0, 0, 0);
String text;
if (value > 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);

View file

@ -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;
}
}
}

View file

@ -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();
}
}

View file

@ -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<QuestCollect> 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<QuestCollect> 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;
}
}

View file

@ -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;
}
}

View file

@ -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<QuestDropItem> 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<QuestDropItem> getItems() {
return items;
}
public void setItems(RealmList<QuestDropItem> items) {
this.items = items;
if (items != null) {
for (QuestDropItem item : items) {
item.setQuestKey(key);
}
}
}
}

View file

@ -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<ShopCategory> 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());
}
}

View file

@ -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);
}
}

View file

@ -12,7 +12,7 @@ public class ShopItemUnlockCondition {
case "party invite":
return R.string.party_invite;
default:
return 0;
return R.string.empty;
}
}
}

View file

@ -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;
}

View file

@ -190,9 +190,14 @@ public class ShopRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
} else if (item.getCurrency().equals("gems")) {
currencyIconView.setImageResource(R.drawable.currency_gem);
priceLabel.setTextColor(ContextCompat.getColor(context, R.color.good_10));
} else if (item.getCurrency().equals("hourglasses")) {
currencyIconView.setImageResource(R.drawable.currency_hourglass);
priceLabel.setTextColor(ContextCompat.getColor(context, R.color.brand_300));
} else {
buyButton.setVisibility(View.GONE);
}
} else {
priceLabel.setText(item.getUnlockCondition().readableUnlockConditionId());
}
if (item.isLimited()) {
@ -282,19 +287,7 @@ public class ShopRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}, CallerThreadExecutor.getInstance());
descriptionView.setText(Html.fromHtml(shop.getNotes()));
switch (shop.getIdentifier()) {
case "market":
namePlate.setText(R.string.market_owner);
break;
case "questShop":
namePlate.setText(R.string.questShop_owner);
break;
case "seasonalShop":
namePlate.setText(R.string.seasonalShop_owner);
break;
case "timetravelers":
namePlate.setText(R.string.timetravelers_owner);
}
namePlate.setText(shop.getNpcNameResource());
}
}

View file

@ -102,7 +102,7 @@ public class ShopsFragment extends BaseMainFragment {
@Override
public int getCount() {
return 3;
return 4;
}
@Override

View file

@ -151,15 +151,15 @@ public class GroupInformationFragment extends BaseFragment {
return;
}
boolean showHpBar = (quest.boss != null && quest.boss.hp > 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) {

View file

@ -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) {

View file

@ -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);
}
}
}

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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());
}
}

View file

@ -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());
}
}

View file

@ -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<String> 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);
}
}

View file

@ -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);

View file

@ -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<RealmList<QuestDropItem>> {
@Override
public RealmList<QuestDropItem> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
RealmList<QuestDropItem> items = new RealmList<>();
List<String> 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;
}
}

View file

@ -37,9 +37,7 @@ public class QuestListDeserializer implements JsonDeserializer<List<QuestContent
item.setPrevious(parsedItem.getPrevious());
item.setCanBuy(parsedItem.isCanBuy());
item.setBoss(parsedItem.getBoss());
if (item.getBoss() != null) {
item.getBoss().key = item.getKey();
}
item.setDrop(parsedItem.getDrop());
item.setCategory(parsedItem.getCategory());
item.setCollect(parsedItem.getCollect());
item.setLvl(parsedItem.getLvl());
@ -55,6 +53,9 @@ public class QuestListDeserializer implements JsonDeserializer<List<QuestContent
QuestContent item;
if (entry.getValue().isJsonObject()) {
item = context.deserialize(entry.getValue(), QuestContent.class);
//Make sure keys are set
item.setBoss(item.getBoss());
item.setDrop(item.getDrop());
} else {
item = new QuestContent();
item.setKey(entry.getKey());