diff --git a/Habitica/AndroidManifest.xml b/Habitica/AndroidManifest.xml
index a4497923a..633ac7c85 100644
--- a/Habitica/AndroidManifest.xml
+++ b/Habitica/AndroidManifest.xml
@@ -48,7 +48,10 @@
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/layout/skill_task_item_card.xml b/Habitica/res/layout/skill_task_item_card.xml
new file mode 100644
index 000000000..0ece71509
--- /dev/null
+++ b/Habitica/res/layout/skill_task_item_card.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index 095745a42..f966c8b0b 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -179,4 +179,5 @@
Profile Image
%d MP
+ You used %1$s for %2$d mana.
\ No newline at end of file
diff --git a/Habitica/src/com/habitrpg/android/habitica/SkillTasksActivity.java b/Habitica/src/com/habitrpg/android/habitica/SkillTasksActivity.java
new file mode 100644
index 000000000..6d1c8f966
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/SkillTasksActivity.java
@@ -0,0 +1,109 @@
+package com.habitrpg.android.habitica;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.design.widget.TabLayout;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.app.FragmentStatePagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v7.app.AppCompatActivity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.habitrpg.android.habitica.ui.adapter.HabitItemRecyclerViewAdapter;
+import com.habitrpg.android.habitica.ui.adapter.SkillTasksRecyclerViewAdapter;
+import com.habitrpg.android.habitica.ui.fragments.SkillTasksRecyclerViewFragment;
+import com.habitrpg.android.habitica.ui.fragments.TaskRecyclerViewFragment;
+import com.habitrpg.android.habitica.ui.fragments.TasksFragment;
+import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
+import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+
+/**
+ * Created by viirus on 28/11/15.
+ */
+public class SkillTasksActivity extends AppCompatActivity {
+ @InjectView(R.id.viewpager)
+ public ViewPager viewPager;
+
+ @InjectView(R.id.tab_layout)
+ public TabLayout tabLayout;
+
+ Map ViewFragmentsDictionary = new HashMap<>();
+ protected HabitRPGUser user;
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_skill_tasks);
+
+ ButterKnife.inject(this);
+
+ loadTaskLists();
+ }
+
+ public void loadTaskLists() {
+ android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
+
+ viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
+
+ @Override
+ public Fragment getItem(int position) {
+ SkillTasksRecyclerViewFragment fragment;
+
+ switch (position) {
+ case 0:
+ fragment = SkillTasksRecyclerViewFragment.newInstance(new SkillTasksRecyclerViewAdapter(Task.TYPE_HABIT, SkillTasksActivity.this), Task.TYPE_HABIT);
+ break;
+ case 1:
+ fragment = SkillTasksRecyclerViewFragment.newInstance(new SkillTasksRecyclerViewAdapter(Task.TYPE_DAILY, SkillTasksActivity.this), Task.TYPE_DAILY);
+
+ break;
+ default:
+ fragment = SkillTasksRecyclerViewFragment.newInstance(new SkillTasksRecyclerViewAdapter(Task.TYPE_TODO, SkillTasksActivity.this), Task.TYPE_TODO);
+ }
+
+ ViewFragmentsDictionary.put(position, fragment);
+
+ return fragment;
+ }
+
+ @Override
+ public int getCount() {
+ return 3;
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ switch (position) {
+ case 0:
+ return "Habits";
+ case 1:
+ return "Dailies";
+ case 2:
+ return "Todos";
+ }
+ return "";
+ }
+ });
+
+
+ tabLayout.setupWithViewPager(viewPager);
+ }
+
+ public void taskSelected(String taskId) {
+ Intent resultIntent = new Intent();
+ resultIntent.putExtra("task_id", taskId);
+ setResult(Activity.RESULT_OK, resultIntent);
+ finish();
+ }
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/callbacks/SkillCallback.java b/Habitica/src/com/habitrpg/android/habitica/callbacks/SkillCallback.java
new file mode 100644
index 000000000..24628f8e4
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/callbacks/SkillCallback.java
@@ -0,0 +1,42 @@
+package com.habitrpg.android.habitica.callbacks;
+
+import android.util.Log;
+
+import com.crashlytics.android.Crashlytics;
+import com.habitrpg.android.habitica.events.SkillUsedEvent;
+import com.habitrpg.android.habitica.events.TaskCreatedEvent;
+import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
+import com.magicmicky.habitrpgwrapper.lib.models.Skill;
+import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
+
+import de.greenrobot.event.EventBus;
+import retrofit.Callback;
+import retrofit.RetrofitError;
+import retrofit.client.Response;
+
+/**
+ * Created by viirus on 28/11/15.
+ */
+public class SkillCallback implements Callback {
+
+ private Skill usedSkill;
+ private final HabitRPGUserCallback.OnUserReceived callback;
+
+ public SkillCallback(HabitRPGUserCallback.OnUserReceived callback, Skill usedSkill) {
+ this.callback = callback;
+ this.usedSkill = usedSkill;
+ }
+
+ @Override
+ public void success(HabitRPGUser habitRPGUser, Response response) {
+ habitRPGUser.async().save();
+ EventBus.getDefault().post(new SkillUsedEvent(this.usedSkill, habitRPGUser.getStats().getMp()));
+ callback.onUserReceived(habitRPGUser);
+ }
+
+ @Override
+ public void failure(RetrofitError error) {
+ Crashlytics.logException(error);
+ callback.onUserFail();
+ }
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/events/SkillUsedEvent.java b/Habitica/src/com/habitrpg/android/habitica/events/SkillUsedEvent.java
new file mode 100644
index 000000000..58e787dbc
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/events/SkillUsedEvent.java
@@ -0,0 +1,17 @@
+package com.habitrpg.android.habitica.events;
+
+import com.magicmicky.habitrpgwrapper.lib.models.Skill;
+
+/**
+ * Created by viirus on 28/11/15.
+ */
+public class SkillUsedEvent {
+
+ public Skill usedSkill;
+ public Double newMana;
+
+ public SkillUsedEvent(Skill usedSkill, Double newMana) {
+ this.usedSkill = usedSkill;
+ this.newMana = newMana;
+ }
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/events/commands/UseSkillCommand.java b/Habitica/src/com/habitrpg/android/habitica/events/commands/UseSkillCommand.java
new file mode 100644
index 000000000..2827743d2
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/events/commands/UseSkillCommand.java
@@ -0,0 +1,11 @@
+package com.habitrpg.android.habitica.events.commands;
+
+import com.magicmicky.habitrpgwrapper.lib.models.Skill;
+
+/**
+ * Created by viirus on 28/11/15.
+ */
+public class UseSkillCommand {
+
+ public Skill skill;
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/adapter/SkillTasksRecyclerViewAdapter.java b/Habitica/src/com/habitrpg/android/habitica/ui/adapter/SkillTasksRecyclerViewAdapter.java
new file mode 100644
index 000000000..e1e32f770
--- /dev/null
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/adapter/SkillTasksRecyclerViewAdapter.java
@@ -0,0 +1,168 @@
+package com.habitrpg.android.habitica.ui.adapter;
+
+import android.app.Activity;
+import android.content.Context;
+import android.databinding.DataBindingUtil;
+import android.databinding.ObservableArrayList;
+import android.os.Handler;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.habitrpg.android.habitica.R;
+import com.habitrpg.android.habitica.SkillTasksActivity;
+import com.habitrpg.android.habitica.databinding.SkillTaskItemCardBinding;
+import com.habitrpg.android.habitica.events.TaskLongPressedEvent;
+import com.habitrpg.android.habitica.events.TaskTappedEvent;
+import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
+import com.raizlabs.android.dbflow.sql.builder.Condition;
+import com.raizlabs.android.dbflow.sql.language.OrderBy;
+import com.raizlabs.android.dbflow.sql.language.Select;
+import com.raizlabs.android.dbflow.structure.BaseModel;
+import com.raizlabs.android.dbflow.structure.Model;
+
+import java.util.UUID;
+
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+import de.greenrobot.event.EventBus;
+
+
+public class SkillTasksRecyclerViewAdapter extends RecyclerView.Adapter {
+
+
+ String taskType;
+ private ObservableArrayList observableContent;
+ SkillTasksActivity activity;
+
+ static final int TYPE_CELL = 1;
+ private RecyclerView.Adapter parentAdapter;
+
+ public SkillTasksRecyclerViewAdapter(String taskType, SkillTasksActivity activity) {
+ this.setHasStableIds(true);
+ this.taskType = taskType;
+ this.activity = activity;
+
+ this.loadContent();
+
+ }
+
+ public void setParentAdapter(RecyclerView.Adapter parentAdapter) {
+ this.parentAdapter = parentAdapter;
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ switch (position) {
+ default:
+ return TYPE_CELL;
+ }
+ }
+
+ @Override
+ public long getItemId(int position) {
+ Task task = observableContent.get(position);
+ if (task.getId() != null && task.getId().length() == 36) {
+ return UUID.fromString(task.getId()).getMostSignificantBits();
+ }
+ return UUID.randomUUID().getMostSignificantBits();
+ }
+
+ @Override
+ public int getItemCount() {
+ return observableContent.size();
+ }
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = null;
+ view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.skill_task_item_card, parent, false);
+ return new SkillTasksRecyclerViewAdapter.ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ Task item = observableContent.get(position);
+
+ holder.bindHolder(item, position);
+ }
+
+ // region ViewHolders
+
+ public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
+
+ protected android.content.res.Resources resources;
+
+ public Task task;
+
+ SkillTaskItemCardBinding binding;
+
+ @InjectView(R.id.notesTextView)
+ TextView notesTextView;
+
+ public ViewHolder(View itemView) {
+ super(itemView);
+
+ itemView.setOnClickListener(this);
+ itemView.setClickable(true);
+
+ ButterKnife.inject(this, itemView);
+ binding = DataBindingUtil.bind(itemView);
+
+ resources = itemView.getResources();
+ }
+
+ public void bindHolder(Task habitItem, int position) {
+ double itemvalue = habitItem.getValue();
+ task = habitItem;
+ if (habitItem.notes == null || habitItem.notes.length() == 0) {
+ notesTextView.setHeight(0);
+ } else {
+ notesTextView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ }
+ binding.setTask(task);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v != itemView)
+ return;
+ activity.taskSelected(task.getId());
+ }
+
+ }
+
+ // endregion
+
+ public void loadContent() {
+ this.loadContent(false);
+ }
+
+ public void loadContent(boolean forced) {
+
+ if (this.observableContent == null || forced) {
+
+ this.observableContent = new ObservableArrayList<>();
+
+ this.observableContent.addAll(new Select().from(Task.class)
+ .where(Condition.column("type").eq(this.taskType))
+ .and(Condition.CombinedCondition
+ .begin(Condition.column("completed").eq(false))
+ .or(Condition.column("type").eq("daily"))
+ )
+ .orderBy(OrderBy.columns("dateCreated").descending())
+ .queryList());
+ }
+
+ if (parentAdapter != null) {
+ parentAdapter.notifyDataSetChanged();
+ } else {
+ notifyDataSetChanged();
+ }
+ }
+}
diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/adapter/SkillsRecyclerViewAdapter.java b/Habitica/src/com/habitrpg/android/habitica/ui/adapter/SkillsRecyclerViewAdapter.java
index 6e57b2c09..7e19997a2 100644
--- a/Habitica/src/com/habitrpg/android/habitica/ui/adapter/SkillsRecyclerViewAdapter.java
+++ b/Habitica/src/com/habitrpg/android/habitica/ui/adapter/SkillsRecyclerViewAdapter.java
@@ -17,6 +17,7 @@ import android.widget.TextView;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.databinding.ValueBarBinding;
+import com.habitrpg.android.habitica.events.TaskTappedEvent;
import com.habitrpg.android.habitica.events.commands.CopyChatAsTodoCommand;
import com.habitrpg.android.habitica.events.commands.DeleteChatMessageCommand;
import com.habitrpg.android.habitica.events.commands.FlagChatMessageCommand;
@@ -24,6 +25,7 @@ import com.habitrpg.android.habitica.events.commands.OpenNewPMActivityCommand;
import com.habitrpg.android.habitica.events.commands.SendNewGroupMessageCommand;
import com.habitrpg.android.habitica.events.commands.ToggleInnCommand;
import com.habitrpg.android.habitica.events.commands.ToggleLikeMessageCommand;
+import com.habitrpg.android.habitica.events.commands.UseSkillCommand;
import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel;
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils;
import com.habitrpg.android.habitica.ui.helpers.ViewHelper;
@@ -59,6 +61,11 @@ public class SkillsRecyclerViewAdapter extends RecyclerView.Adapter habitRPGUserCallback);
+ @POST("/user/class/cast/{skill}")
+ void useSkill(@Path("skill") String skillName, @Query("targetType") String targetType, @Query("targetId") String targetId, Callback habitRPGUserCallback);
+
+ @POST("/user/class/cast/{skill}")
+ void useSkill(@Path("skill") String skillName, @Query("targetType") String targetType, Callback habitRPGUserCallback);
+
/* Group API */
@GET("/groups")