diff --git a/Habitica/res/layout/customization_grid_item.xml b/Habitica/res/layout/customization_grid_item.xml
index f313afe72..0fb0876f3 100644
--- a/Habitica/res/layout/customization_grid_item.xml
+++ b/Habitica/res/layout/customization_grid_item.xml
@@ -3,22 +3,35 @@
android:id="@+id/card_view"
android:layout_height="wrap_content"
android:layout_width="match_parent">
-
+
-
+ android:scaleType="fitEnd"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:layout_centerVertical="true"
+ android:layout_centerHorizontal="true" />
+
+
\ No newline at end of file
diff --git a/Habitica/res/layout/customization_section_header.xml b/Habitica/res/layout/customization_section_header.xml
index 3e52c9937..5d3039267 100644
--- a/Habitica/res/layout/customization_section_header.xml
+++ b/Habitica/res/layout/customization_section_header.xml
@@ -4,8 +4,15 @@
android:layout_height="match_parent">
+ android:layout_weight="1"
+ android:layout_gravity="bottom"
+ android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+
\ No newline at end of file
diff --git a/Habitica/res/layout/dialog_purchase_customization.xml b/Habitica/res/layout/dialog_purchase_customization.xml
new file mode 100644
index 000000000..b976c43f7
--- /dev/null
+++ b/Habitica/res/layout/dialog_purchase_customization.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index d1adf6b3d..7da8e2132 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -155,4 +155,6 @@
Size
Slim
Broad
+ Purchase Customization
+ Unlock set for %d gems
\ No newline at end of file
diff --git a/Habitica/src/com/habitrpg/android/habitica/APIHelper.java b/Habitica/src/com/habitrpg/android/habitica/APIHelper.java
index 6a00128d5..8163b7ead 100644
--- a/Habitica/src/com/habitrpg/android/habitica/APIHelper.java
+++ b/Habitica/src/com/habitrpg/android/habitica/APIHelper.java
@@ -1,7 +1,5 @@
package com.habitrpg.android.habitica;
-import android.app.Activity;
-import android.content.Context;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
@@ -9,11 +7,6 @@ import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
@@ -26,9 +19,10 @@ import com.magicmicky.habitrpgwrapper.lib.api.ApiService;
import com.magicmicky.habitrpgwrapper.lib.api.InAppPurchasesApiService;
import com.magicmicky.habitrpgwrapper.lib.api.Server;
import com.magicmicky.habitrpgwrapper.lib.api.TypeAdapter.TagsAdapter;
-import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
+import com.magicmicky.habitrpgwrapper.lib.models.Customization;
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationRequest;
import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationResult;
+import com.magicmicky.habitrpgwrapper.lib.models.Purchases;
import com.magicmicky.habitrpgwrapper.lib.models.SkillList;
import com.magicmicky.habitrpgwrapper.lib.models.TaskDirection;
import com.magicmicky.habitrpgwrapper.lib.models.UserAuth;
@@ -39,6 +33,8 @@ import com.magicmicky.habitrpgwrapper.lib.models.tasks.ChecklistItem;
import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
import com.magicmicky.habitrpgwrapper.lib.models.tasks.TaskTag;
import com.magicmicky.habitrpgwrapper.lib.utils.ChecklistItemSerializer;
+import com.magicmicky.habitrpgwrapper.lib.utils.CustomizationDeserializer;
+import com.magicmicky.habitrpgwrapper.lib.utils.PurchasedDeserializer;
import com.magicmicky.habitrpgwrapper.lib.utils.SkillDeserializer;
import com.magicmicky.habitrpgwrapper.lib.utils.TaskListDeserializer;
import com.raizlabs.android.dbflow.structure.ModelAdapter;
@@ -53,7 +49,6 @@ import retrofit.Profiler;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
-import retrofit.converter.ConversionException;
import retrofit.converter.GsonConverter;
@@ -84,6 +79,7 @@ public class APIHelper implements ErrorHandler, Profiler {
Type taskClassListType = new TypeToken>() {}.getType();
+ Type customizationListType = new TypeToken>() {}.getType();
//Exclusion stratety needed for DBFlow https://github.com/Raizlabs/DBFlow/issues/121
Gson gson = new GsonBuilder()
@@ -105,6 +101,8 @@ public class APIHelper implements ErrorHandler, Profiler {
.registerTypeAdapter(SkillList.class, new SkillDeserializer())
.registerTypeAdapter(ChecklistItem.class, new ChecklistItemSerializer())
.registerTypeAdapter(taskClassListType, new TaskListDeserializer())
+ .registerTypeAdapter(Purchases.class, new PurchasedDeserializer())
+ .registerTypeAdapter(customizationListType, new CustomizationDeserializer())
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.create();
diff --git a/Habitica/src/com/habitrpg/android/habitica/callbacks/UnlockCallback.java b/Habitica/src/com/habitrpg/android/habitica/callbacks/UnlockCallback.java
new file mode 100644
index 000000000..5cdfbe2f9
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/callbacks/UnlockCallback.java
@@ -0,0 +1,40 @@
+package com.habitrpg.android.habitica.callbacks;
+
+import com.crashlytics.android.Crashlytics;
+import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
+import com.magicmicky.habitrpgwrapper.lib.models.responses.UnlockResponse;
+
+import retrofit.Callback;
+import retrofit.RetrofitError;
+import retrofit.client.Response;
+
+/**
+ * Created by magicmicky on 18/02/15.
+ */
+public class UnlockCallback implements Callback {
+
+ private final HabitRPGUserCallback.OnUserReceived mCallback;
+
+ private HabitRPGUser user;
+
+ public UnlockCallback(HabitRPGUserCallback.OnUserReceived callback, HabitRPGUser user) {
+ this.mCallback = callback;
+ this.user = user;
+ }
+
+ @Override
+ public void success(UnlockResponse unlockResponse, Response response) {
+ this.user.setPurchased(unlockResponse.purchased);
+ this.user.setItems(unlockResponse.items);
+ this.user.setPreferences(unlockResponse.preferences);
+
+ this.user.async().save();
+
+ mCallback.onUserReceived(this.user);
+ }
+
+ @Override
+ public void failure(RetrofitError error) {
+ mCallback.onUserFail();
+ }
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/events/commands/OpenMenuItemCommand.java b/Habitica/src/com/habitrpg/android/habitica/events/commands/OpenMenuItemCommand.java
new file mode 100644
index 000000000..7e3b56b42
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/events/commands/OpenMenuItemCommand.java
@@ -0,0 +1,8 @@
+package com.habitrpg.android.habitica.events.commands;
+
+/**
+ * Created by viirus on 15/01/16.
+ */
+public class OpenMenuItemCommand {
+ public int identifier;
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/events/commands/UnlockPathCommand.java b/Habitica/src/com/habitrpg/android/habitica/events/commands/UnlockPathCommand.java
new file mode 100644
index 000000000..320e5e39d
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/events/commands/UnlockPathCommand.java
@@ -0,0 +1,11 @@
+package com.habitrpg.android.habitica.events.commands;
+
+/**
+ * Created by viirus on 15/01/16.
+ */
+public class UnlockPathCommand {
+
+ public String path;
+ public double balanceDiff;
+
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/com/habitrpg/android/habitica/ui/activities/MainActivity.java
index eb6c69d08..469562543 100644
--- a/Habitica/src/com/habitrpg/android/habitica/ui/activities/MainActivity.java
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/activities/MainActivity.java
@@ -31,12 +31,15 @@ import com.habitrpg.android.habitica.NotificationPublisher;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.callbacks.HabitRPGUserCallback;
import com.habitrpg.android.habitica.callbacks.TaskScoringCallback;
+import com.habitrpg.android.habitica.callbacks.UnlockCallback;
import com.habitrpg.android.habitica.databinding.ValueBarBinding;
import com.habitrpg.android.habitica.events.TaskRemovedEvent;
import com.habitrpg.android.habitica.events.ToggledInnStateEvent;
import com.habitrpg.android.habitica.events.commands.BuyRewardCommand;
import com.habitrpg.android.habitica.events.commands.DeleteTaskCommand;
import com.habitrpg.android.habitica.events.commands.OpenGemPurchaseFragmentCommand;
+import com.habitrpg.android.habitica.events.commands.OpenMenuItemCommand;
+import com.habitrpg.android.habitica.events.commands.UnlockPathCommand;
import com.habitrpg.android.habitica.events.commands.UpdateUserCommand;
import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel;
import com.habitrpg.android.habitica.ui.MainDrawerBuilder;
@@ -466,6 +469,15 @@ public class MainActivity extends BaseActivity implements HabitRPGUserCallback.O
mAPIHelper.apiService.updateUser(event.updateData, new HabitRPGUserCallback(this));
}
+ public void onEvent(UnlockPathCommand event) {
+ this.user.setBalance(this.user.getBalance() - event.balanceDiff);
+ mAPIHelper.apiService.unlockPath(event.path, new UnlockCallback(this, this.user));
+ }
+
+ public void onEvent(OpenMenuItemCommand event) {
+ drawer.setSelection(event.identifier);
+ }
+
public void onEvent(final BuyRewardCommand event) {
final String rewardKey = event.Reward.getId();
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.java b/Habitica/src/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.java
index 5bbd95e5f..bfd67199a 100644
--- a/Habitica/src/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.java
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.java
@@ -1,6 +1,6 @@
package com.habitrpg.android.habitica.ui.adapter;
-import android.content.res.Resources;
+import android.content.Context;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@@ -9,13 +9,19 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
import android.widget.TextView;
+import com.afollestad.materialdialogs.DialogAction;
+import com.afollestad.materialdialogs.GravityEnum;
+import com.afollestad.materialdialogs.MaterialDialog;
import com.habitrpg.android.habitica.R;
+import com.habitrpg.android.habitica.events.commands.OpenMenuItemCommand;
+import com.habitrpg.android.habitica.events.commands.UnlockPathCommand;
import com.habitrpg.android.habitica.events.commands.UpdateUserCommand;
+import com.habitrpg.android.habitica.ui.MainDrawerBuilder;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.magicmicky.habitrpgwrapper.lib.models.Customization;
-import com.raizlabs.android.dbflow.sql.language.Update;
import java.util.ArrayList;
import java.util.HashMap;
@@ -35,14 +41,15 @@ public class CustomizationRecyclerViewAdapter extends RecyclerView.Adapter newCustomizationList) {
this.customizationList = new ArrayList