From a189179c0514181d8f1dbbb5e43572eae175af7b Mon Sep 17 00:00:00 2001 From: Negue Date: Mon, 27 Mar 2017 18:36:00 +0200 Subject: [PATCH 01/29] init activity --- .../res/layout/activity_create_challenge.xml | 102 ++++++++++++++++++ .../habitica/components/AppComponent.java | 3 + .../activities/CreateChallengeActivity.java | 24 +++++ 3 files changed, 129 insertions(+) create mode 100644 Habitica/res/layout/activity_create_challenge.xml create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java diff --git a/Habitica/res/layout/activity_create_challenge.xml b/Habitica/res/layout/activity_create_challenge.xml new file mode 100644 index 000000000..d34288160 --- /dev/null +++ b/Habitica/res/layout/activity_create_challenge.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java index 0a36d63da..53b52f5c2 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java @@ -13,6 +13,7 @@ import com.habitrpg.android.habitica.receivers.LocalNotificationActionReceiver; import com.habitrpg.android.habitica.ui.activities.AboutActivity; import com.habitrpg.android.habitica.ui.activities.ChallengeDetailActivity; import com.habitrpg.android.habitica.ui.activities.ClassSelectionActivity; +import com.habitrpg.android.habitica.ui.activities.CreateChallengeActivity; import com.habitrpg.android.habitica.ui.activities.FullProfileActivity; import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity; import com.habitrpg.android.habitica.ui.activities.GroupFormActivity; @@ -232,4 +233,6 @@ public interface AppComponent { void inject(TaskListFactory taskListFactory); void inject(GemPurchaseActivity gemPurchaseActivity); + + void inject(CreateChallengeActivity createChallengeActivity); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java new file mode 100644 index 000000000..371167aed --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java @@ -0,0 +1,24 @@ +package com.habitrpg.android.habitica.ui.activities; + +import android.os.Bundle; + +import com.habitrpg.android.habitica.R; +import com.habitrpg.android.habitica.components.AppComponent; + +public class CreateChallengeActivity extends BaseActivity { + + @Override + protected int getLayoutResId() { + return R.id.activity_create_challenge; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + protected void injectActivity(AppComponent component) { + component.inject(this); + } +} From 57e9dd92727791e46a2551777fac77e14825c22f Mon Sep 17 00:00:00 2001 From: Negue Date: Tue, 28 Mar 2017 22:53:28 +0200 Subject: [PATCH 02/29] first control / layout design --- Habitica/AndroidManifest.xml | 10 + .../res/layout/activity_create_challenge.xml | 180 +++++++++++------- .../habitica/HabiticaBaseApplication.java | 5 +- .../activities/CreateChallengeActivity.java | 2 +- .../habitica/ui/activities/MainActivity.java | 1 + 5 files changed, 132 insertions(+), 66 deletions(-) diff --git a/Habitica/AndroidManifest.xml b/Habitica/AndroidManifest.xml index bd87e8a71..1e0426a9f 100644 --- a/Habitica/AndroidManifest.xml +++ b/Habitica/AndroidManifest.xml @@ -140,6 +140,16 @@ android:name="android.support.PARENT_ACTIVITY" android:value=".ui.activities.MainActivity" /> + + + - + android:orientation="vertical" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin"> - - - + android:textColorHint="@color/brand_500" + app:hintTextAppearance="@style/TextAppearance.AppCompat"> - + + + - - + + + + + + + + android:layout_height="2dp" + android:background="@color/brand_700"/> + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin"> + android:text="Gem reward" + style="@style/Body1"/> - + + + + \ No newline at end of file diff --git a/Habitica/res/menu/menu_create_challenge.xml b/Habitica/res/menu/menu_create_challenge.xml new file mode 100644 index 000000000..6475f0388 --- /dev/null +++ b/Habitica/res/menu/menu_create_challenge.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml index 4299cd0a6..6e8456de1 100644 --- a/Habitica/res/values/strings.xml +++ b/Habitica/res/values/strings.xml @@ -544,4 +544,8 @@ To start, which parts of your life do you want to improve? Back Oh, you must be new here. I’m Justin, I’ll be your guide in Habitica.\n\nTo start, you’ll need to create an avatar. Randomize + Save + Location + Gem reward + Tasks diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java index 53b52f5c2..c38adbe3d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java @@ -28,6 +28,7 @@ import com.habitrpg.android.habitica.ui.activities.SetupActivity; import com.habitrpg.android.habitica.ui.activities.SkillMemberActivity; import com.habitrpg.android.habitica.ui.activities.SkillTasksActivity; import com.habitrpg.android.habitica.ui.activities.TaskFormActivity; +import com.habitrpg.android.habitica.ui.adapter.social.challenges.ChallengeTasksRecyclerViewAdapter; import com.habitrpg.android.habitica.ui.adapter.tasks.DailiesRecyclerViewHolder; import com.habitrpg.android.habitica.ui.adapter.tasks.HabitsRecyclerViewAdapter; import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter; @@ -226,7 +227,7 @@ public interface AppComponent { void inject(SubscriptionFragment subscriptionFragment); - void inject(ChallengeTasksRecyclerViewFragment.ChallengeTasksRecyclerViewAdapter challengeTasksRecyclerViewAdapter); + void inject(ChallengeTasksRecyclerViewAdapter challengeTasksRecyclerViewAdapter); void inject(ChallengeTasksRecyclerViewFragment challengeTasksRecyclerViewFragment); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java index 2edb07d06..0e18992b2 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java @@ -1,20 +1,172 @@ package com.habitrpg.android.habitica.ui.activities; +import android.content.Intent; +import android.content.res.Resources; +import android.graphics.drawable.ColorDrawable; import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.support.v7.view.menu.MenuAdapter; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MotionEvent; +import android.widget.ArrayAdapter; +import android.widget.Spinner; +import com.habitrpg.android.habitica.HabiticaApplication; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.components.AppComponent; +import com.habitrpg.android.habitica.events.TaskSaveEvent; +import com.habitrpg.android.habitica.ui.adapter.social.challenges.ChallengeTasksRecyclerViewAdapter; +import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeTasksRecyclerViewFragment; +import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.util.ArrayList; +import java.util.UUID; + +import butterknife.BindView; public class CreateChallengeActivity extends BaseActivity { + @BindView(R.id.challenge_location_spinner) + Spinner challenge_location_spinner; + + + @BindView(R.id.create_challenge_task_list) + RecyclerView create_challenge_task_list; + + private boolean displayingTaskForm; + @Override protected int getLayoutResId() { return R.layout.activity_create_challenge; } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.menu_create_challenge, menu); + return true; + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + EventBus.getDefault().register(this); + + Resources resources = getResources(); + + ActionBar supportActionBar = getSupportActionBar(); + if (supportActionBar != null) { + supportActionBar.setIcon(R.drawable.ic_close_white_24dp); + + supportActionBar.setBackgroundDrawable(new ColorDrawable(resources.getColor(R.color.brand_200))); + supportActionBar.setElevation(0); + } + + ArrayAdapter locationAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item); + locationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + locationAdapter.addAll("Tavern", "My Group", "Some other"); + challenge_location_spinner.setAdapter(locationAdapter); + + Task addHabit = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_habit)); + Task addDaily = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_daily)); + Task addTodo = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_todo)); + Task addReward = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_reward)); + + ArrayList taskList = new ArrayList<>(); + taskList.add(addHabit); + taskList.add(createTask(Task.TYPE_HABIT)); + taskList.add(addDaily); + taskList.add(createTask(Task.TYPE_DAILY)); + taskList.add(addTodo); + taskList.add(createTask(Task.TYPE_TODO)); + taskList.add(addReward); + taskList.add(createTask(Task.TYPE_REWARD)); + + ChallengeTasksRecyclerViewAdapter challengeTasks = new ChallengeTasksRecyclerViewAdapter(null, 0, this, "", null, false, true); + challengeTasks.setTasks(taskList); + challengeTasks.enableAddItem(t -> { + if (t.equals(addHabit)) { + openNewTaskActivity(Task.TYPE_HABIT); + } else if (t.equals(addDaily)) { + + openNewTaskActivity(Task.TYPE_DAILY); + } else if (t.equals(addTodo)) { + + openNewTaskActivity(Task.TYPE_TODO); + } else if (t.equals(addReward)) { + + openNewTaskActivity(Task.TYPE_REWARD); + } + }); + + create_challenge_task_list.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() { + @Override + public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { + // Stop only scrolling. + return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING; + } + }); + create_challenge_task_list.setAdapter(challengeTasks); + create_challenge_task_list.setLayoutManager(new LinearLayoutManager(this)); + + } + + private void openNewTaskActivity(String type) { + if (this.displayingTaskForm) { + return; + } + + Bundle bundle = new Bundle(); + bundle.putString(TaskFormActivity.TASK_TYPE_KEY, type); + bundle.putBoolean(TaskFormActivity.SAVE_TO_DB, false); + + if (HabiticaApplication.User != null && HabiticaApplication.User.getPreferences() != null) { + String allocationMode = HabiticaApplication.User.getPreferences().getAllocationMode(); + + bundle.putString(TaskFormActivity.USER_ID_KEY, HabiticaApplication.User.getId()); + bundle.putString(TaskFormActivity.ALLOCATION_MODE_KEY, allocationMode); + } + + + Intent intent = new Intent(this, TaskFormActivity.class); + intent.putExtras(bundle); + intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + + this.displayingTaskForm = true; + startActivityForResult(intent, 1); + } + + @Subscribe + public void onEvent(TaskSaveEvent saveEvent) + { + + } + + private Task createTask(String taskType) { + return createTask(taskType, "example " + taskType); + } + + private Task createTask(String taskType, String taskName) { + Task t = new Task(); + + t.setId(UUID.randomUUID().toString()); + t.setType(taskType); + t.setText(taskName); + t.setNotes("example " + taskType + " notes"); + + if (taskType.equals(Task.TYPE_HABIT)) { + t.setUp(true); + t.setDown(false); + } + + return t; } @Override diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java index 5057b4d88..8e3fe3f03 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java @@ -88,6 +88,7 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem public static final String USER_ID_KEY = "userId"; public static final String TASK_TYPE_KEY = "type"; public static final String ALLOCATION_MODE_KEY = "allocationModeKey"; + public static final String SAVE_TO_DB = "saveToDb"; @BindView(R.id.task_value_edittext) EditText taskValue; @@ -214,6 +215,7 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem private RemindersManager remindersManager; private TaskAlarmManager taskAlarmManager; private FirstDayOfTheWeekHelper firstDayOfTheWeekHelper; + private boolean saveToDb; @Override protected int getLayoutResId() { @@ -230,6 +232,7 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem taskId = bundle.getString(TASK_ID_KEY); userId = bundle.getString(USER_ID_KEY); allocationMode = bundle.getString(ALLOCATION_MODE_KEY); + saveToDb = bundle.getBoolean(SAVE_TO_DB, true); tagCheckBoxList = new ArrayList<>(); selectedTags = new ArrayList<>(); if (taskType == null) { @@ -873,7 +876,10 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem } //save this.task.setTags(taskTags); - this.task.save(); + if(saveToDb){ + this.task.save(); + } + //send back to other elements. TaskSaveEvent event = new TaskSaveEvent(); if (TaskFormActivity.this.task.getId() == null) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/challenges/ChallengeTasksRecyclerViewAdapter.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/challenges/ChallengeTasksRecyclerViewAdapter.java new file mode 100644 index 000000000..135b43a95 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/challenges/ChallengeTasksRecyclerViewAdapter.java @@ -0,0 +1,155 @@ +package com.habitrpg.android.habitica.ui.adapter.social.challenges; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.habitrpg.android.habitica.R; +import com.habitrpg.android.habitica.components.AppComponent; +import com.habitrpg.android.habitica.helpers.TagsHelper; +import com.habitrpg.android.habitica.ui.adapter.tasks.SortableTasksRecyclerViewAdapter; +import com.habitrpg.android.habitica.ui.viewHolders.tasks.BaseTaskViewHolder; +import com.habitrpg.android.habitica.ui.viewHolders.tasks.DailyViewHolder; +import com.habitrpg.android.habitica.ui.viewHolders.tasks.HabitViewHolder; +import com.habitrpg.android.habitica.ui.viewHolders.tasks.RewardViewHolder; +import com.habitrpg.android.habitica.ui.viewHolders.tasks.TodoViewHolder; +import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task; + +import butterknife.OnClick; +import rx.functions.Action1; + +public class ChallengeTasksRecyclerViewAdapter extends SortableTasksRecyclerViewAdapter { + public static final String TASK_TYPE_ADD_ITEM = "ADD_ITEM"; + + private static final int TYPE_HEADER = 0; + private static final int TYPE_HABIT = 1; + private static final int TYPE_DAILY = 2; + private static final int TYPE_TODO = 3; + private static final int TYPE_REWARD = 4; + private static final int TYPE_ADD_ITEM = 5; + + private int dailyResetOffset = 0; + private Action1 addItemCallback; + private boolean openTaskDisabled; + private boolean taskActionsDisabled; + + public ChallengeTasksRecyclerViewAdapter(TagsHelper tagsHelper, int layoutResource, + Context newContext, String userID, SortTasksCallback sortCallback, + boolean openTaskDisabled, boolean taskActionsDisabled) { + super("", tagsHelper, layoutResource, newContext, userID, sortCallback); + this.openTaskDisabled = openTaskDisabled; + this.taskActionsDisabled = taskActionsDisabled; + } + + public void setDailyResetOffset(int newResetOffset){ + dailyResetOffset = newResetOffset; + } + + @Override + protected void injectThis(AppComponent component) { + component.inject(this); + } + + @Override + public boolean loadFromDatabase() { + return false; + } + + @Override + public int getItemViewType(int position) { + Task task = this.filteredContent.get(position); + + if (task.type.equals(Task.TYPE_HABIT)) + return TYPE_HABIT; + + if (task.type.equals(Task.TYPE_DAILY)) + return TYPE_DAILY; + + if (task.type.equals(Task.TYPE_TODO)) + return TYPE_TODO; + + if (task.type.equals(Task.TYPE_REWARD)) + return TYPE_REWARD; + + if(addItemCallback != null && task.type.equals(TASK_TYPE_ADD_ITEM)) + return TYPE_ADD_ITEM; + + return TYPE_HEADER; + } + + public void enableAddItem(Action1 cb) { + addItemCallback = cb; + } + + @Override + public BaseTaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + BaseTaskViewHolder viewHolder = null; + + switch (viewType) { + case TYPE_HABIT: + viewHolder = new HabitViewHolder(getContentView(parent, R.layout.habit_item_card)); + break; + case TYPE_DAILY: + viewHolder = new DailyViewHolder(getContentView(parent, R.layout.daily_item_card), dailyResetOffset); + break; + case TYPE_TODO: + viewHolder = new TodoViewHolder(getContentView(parent, R.layout.todo_item_card)); + break; + case TYPE_REWARD: + viewHolder = new RewardViewHolder(getContentView(parent, R.layout.reward_item_card)); + break; + case TYPE_ADD_ITEM: + viewHolder = new AddItemViewHolder(getContentView(parent, R.layout.challenge_add_task_item), addItemCallback); + break; + default: + viewHolder = new DividerViewHolder(getContentView(parent, R.layout.challenge_task_divider)); + break; + } + + viewHolder.setDisabled(openTaskDisabled, taskActionsDisabled); + return viewHolder; + } + + public class AddItemViewHolder extends BaseTaskViewHolder { + + private Button addBtn; + private Action1 callback; + private Task newTask; + + public AddItemViewHolder(View itemView, Action1 callback) { + super(itemView, false); + this.callback = callback; + + addBtn = (Button) itemView.findViewById(R.id.btn_add_task); + addBtn.setClickable(true); + addBtn.setOnClickListener(view -> callback.call(newTask)); + context = itemView.getContext(); + } + + @Override + public void bindHolder(Task newTask, int position) { + this.newTask = newTask; + addBtn.setText(newTask.text); + } + } + + private class DividerViewHolder extends BaseTaskViewHolder { + + private TextView divider_name; + + public DividerViewHolder(View itemView) { + super(itemView, false); + + divider_name = (TextView) itemView.findViewById(R.id.divider_name); + + context = itemView.getContext(); + } + + @Override + public void bindHolder(Task newTask, int position) { + divider_name.setText(newTask.text); + } + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeTasksRecyclerViewFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeTasksRecyclerViewFragment.java index eccb79d65..4395bc985 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeTasksRecyclerViewFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeTasksRecyclerViewFragment.java @@ -5,6 +5,7 @@ import com.habitrpg.android.habitica.APIHelper; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.components.AppComponent; import com.habitrpg.android.habitica.helpers.TagsHelper; +import com.habitrpg.android.habitica.ui.adapter.social.challenges.ChallengeTasksRecyclerViewAdapter; import com.habitrpg.android.habitica.ui.adapter.tasks.BaseTasksRecyclerViewAdapter; import com.habitrpg.android.habitica.ui.adapter.tasks.SortableTasksRecyclerViewAdapter; import com.habitrpg.android.habitica.ui.fragments.BaseFragment; @@ -86,7 +87,10 @@ public class ChallengeTasksRecyclerViewFragment extends BaseFragment { } public void setInnerAdapter() { - this.recyclerAdapter = new ChallengeTasksRecyclerViewAdapter(null, 0, getContext(), userID, null); + ChallengeTasksRecyclerViewAdapter challengeTasksRecyclerViewAdapter = new ChallengeTasksRecyclerViewAdapter(null, 0, getContext(), userID, null, true, true); + this.recyclerAdapter = challengeTasksRecyclerViewAdapter; + + challengeTasksRecyclerViewAdapter.setDailyResetOffset(user.getPreferences().getDayStart()); if (tasksOnInitialize.size() != 0 && recyclerAdapter != null && recyclerAdapter.getItemCount() == 0) { recyclerAdapter.setTasks(tasksOnInitialize); @@ -137,96 +141,8 @@ public class ChallengeTasksRecyclerViewFragment extends BaseFragment { // region Challenge specific RecyclerViewAdapters - public class ChallengeTasksRecyclerViewAdapter extends SortableTasksRecyclerViewAdapter { - private static final int TYPE_HEADER = 0; - private static final int TYPE_HABIT = 1; - private static final int TYPE_DAILY = 2; - private static final int TYPE_TODO = 3; - private static final int TYPE_REWARD = 4; - private int dailyResetOffset = 0; - public ChallengeTasksRecyclerViewAdapter(TagsHelper tagsHelper, int layoutResource, Context newContext, String userID, SortTasksCallback sortCallback) { - super("", tagsHelper, layoutResource, newContext, userID, sortCallback); - - if (user != null) { - dailyResetOffset = user.getPreferences().getDayStart(); - } - } - - @Override - protected void injectThis(AppComponent component) { - component.inject(this); - } - - @Override - public boolean loadFromDatabase() { - return false; - } - - @Override - public int getItemViewType(int position) { - Task task = this.filteredContent.get(position); - - if (task.type.equals(Task.TYPE_HABIT)) - return TYPE_HABIT; - - if (task.type.equals(Task.TYPE_DAILY)) - return TYPE_DAILY; - - if (task.type.equals(Task.TYPE_TODO)) - return TYPE_TODO; - - if (task.type.equals(Task.TYPE_REWARD)) - return TYPE_REWARD; - - return TYPE_HEADER; - } - - @Override - public BaseTaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - BaseTaskViewHolder viewHolder = null; - - switch (viewType) { - case TYPE_HABIT: - viewHolder = new HabitViewHolder(getContentView(parent, R.layout.habit_item_card)); - break; - case TYPE_DAILY: - viewHolder = new DailyViewHolder(getContentView(parent, R.layout.daily_item_card), dailyResetOffset); - break; - case TYPE_TODO: - viewHolder = new TodoViewHolder(getContentView(parent, R.layout.todo_item_card)); - break; - case TYPE_REWARD: - viewHolder = new RewardViewHolder(getContentView(parent, R.layout.reward_item_card)); - break; - default: - viewHolder = new DividerViewHolder(getContentView(parent, R.layout.challenge_task_divider)); - break; - } - - viewHolder.setDisabled(true); - return viewHolder; - } - } - - private class DividerViewHolder extends BaseTaskViewHolder { - - private TextView divider_name; - - public DividerViewHolder(View itemView) { - super(itemView, false); - - divider_name = (TextView) itemView.findViewById(R.id.divider_name); - - context = itemView.getContext(); - } - - @Override - public void bindHolder(Task newTask, int position) { - divider_name.setText(newTask.text); - } - } // endregion } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.java index 21e9a23a4..1b100c586 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.java @@ -63,7 +63,6 @@ public abstract class BaseTaskViewHolder extends RecyclerView.ViewHolder impleme @BindView(R.id.approvalRequiredTextField) TextView approvalRequiredTextView; - boolean disabled; public BaseTaskViewHolder(View itemView) { this(itemView, true); @@ -187,7 +186,7 @@ public abstract class BaseTaskViewHolder extends RecyclerView.ViewHolder impleme @Override public void onClick(View v) { - if (v != itemView || isDisabled()) { + if (v != itemView || this.openTaskDisabled) { return; } @@ -201,13 +200,11 @@ public abstract class BaseTaskViewHolder extends RecyclerView.ViewHolder impleme return true; } - public boolean isDisabled() { - return disabled; - } + protected boolean openTaskDisabled, taskActionsDisabled; - public void setDisabled(boolean disabled) { - this.disabled = disabled; + public void setDisabled(boolean openTaskDisabled, boolean taskActionsDisabled) { + this.openTaskDisabled = openTaskDisabled; + this.taskActionsDisabled = taskActionsDisabled; - itemView.setEnabled(!disabled); } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.java index 3431d56c0..7d8fd515f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/ChecklistedViewHolder.java @@ -167,9 +167,9 @@ public abstract class ChecklistedViewHolder extends BaseTaskViewHolder implement } @Override - public void setDisabled(boolean disabled) { - super.setDisabled(disabled); + public void setDisabled(boolean openTaskDisabled, boolean taskActionsDisabled) { + super.setDisabled(openTaskDisabled, taskActionsDisabled); - this.checkbox.setEnabled(!disabled); + this.checkbox.setEnabled(!taskActionsDisabled); } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.java index 86c3116b6..679719c81 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/HabitViewHolder.java @@ -88,10 +88,10 @@ public class HabitViewHolder extends BaseTaskViewHolder { } @Override - public void setDisabled(boolean disabled) { - super.setDisabled(disabled); + public void setDisabled(boolean openTaskDisabled, boolean taskActionsDisabled) { + super.setDisabled(openTaskDisabled, taskActionsDisabled); - this.btnPlus.setEnabled(!disabled); - this.btnMinus.setEnabled(!disabled); + this.btnPlus.setEnabled(!taskActionsDisabled); + this.btnMinus.setEnabled(!taskActionsDisabled); } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.java index f620fd6c5..1412c1032 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/RewardViewHolder.java @@ -85,10 +85,10 @@ public class RewardViewHolder extends BaseTaskViewHolder { } @Override - public void setDisabled(boolean disabled) { - super.setDisabled(disabled); + public void setDisabled(boolean openTaskDisabled, boolean taskActionsDisabled) { + super.setDisabled(openTaskDisabled, taskActionsDisabled); - this.rewardButton.setEnabled(!disabled); + this.rewardButton.setEnabled(!taskActionsDisabled); } } From da87dd587cebedeaceeddac288474c66d18b2c42 Mon Sep 17 00:00:00 2001 From: Negue Date: Thu, 6 Apr 2017 21:19:25 +0200 Subject: [PATCH 04/29] fix compile --- Habitica/AndroidManifest.xml | 2 +- .../social/challenges/ChallengeTasksRecyclerViewAdapter.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Habitica/AndroidManifest.xml b/Habitica/AndroidManifest.xml index 56207f35e..eb8c89e37 100644 --- a/Habitica/AndroidManifest.xml +++ b/Habitica/AndroidManifest.xml @@ -143,7 +143,7 @@ { @@ -40,7 +38,7 @@ public class ChallengeTasksRecyclerViewAdapter extends SortableTasksRecyclerView public ChallengeTasksRecyclerViewAdapter(@Nullable TaskFilterHelper taskFilterHelper, int layoutResource, Context newContext, String userID, @Nullable SortTasksCallback sortCallback, boolean openTaskDisabled, boolean taskActionsDisabled) { - super("", tagsHelper, layoutResource, newContext, userID, sortCallback); + super("", taskFilterHelper, layoutResource, newContext, userID, sortCallback); this.openTaskDisabled = openTaskDisabled; this.taskActionsDisabled = taskActionsDisabled; } From ebd3b1f93ec926b52e45ecdc465f6a1f9e957411 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Wed, 19 Apr 2017 16:53:43 +0200 Subject: [PATCH 05/29] fix login incentive notification --- Habitica/res/layout/dialog_login_incentive.xml | 15 +++------------ .../helpers/PopupNotificationsManager.java | 6 +++++- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Habitica/res/layout/dialog_login_incentive.xml b/Habitica/res/layout/dialog_login_incentive.xml index c0d3c4bf1..11cbd48cd 100644 --- a/Habitica/res/layout/dialog_login_incentive.xml +++ b/Habitica/res/layout/dialog_login_incentive.xml @@ -1,24 +1,19 @@ - + android:gravity="center_horizontal"> - @@ -37,10 +30,8 @@ android:text="@string/see_you_tomorrow" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_below="@+id/next_unlock_message" - android:layout_centerHorizontal="true" android:layout_marginTop="50dp" android:id="@+id/confirm_button" style="@style/Widget.AppCompat.Button.Borderless.Colored" /> - \ No newline at end of file + \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PopupNotificationsManager.java b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PopupNotificationsManager.java index 22ebd93fd..82f3810cb 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PopupNotificationsManager.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PopupNotificationsManager.java @@ -1,6 +1,7 @@ package com.habitrpg.android.habitica.helpers; import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; @@ -70,15 +71,18 @@ public class PopupNotificationsManager { DataBindingUtils.loadImage(imageView, imageKey); TextView youEarnedTexView = (TextView) view.findViewById(R.id.you_earned_message); + youEarnedTexView.setTextColor(ContextCompat.getColor(context, R.color.textColorLight)); youEarnedTexView.setText(youEarnedMessage); String message = context.getString(R.string.nextPrizeUnlocks, notification.data.nextRewardAt); TextView nextUnlockTextView = (TextView) view.findViewById(R.id.next_unlock_message); + nextUnlockTextView.setTextColor(ContextCompat.getColor(context, R.color.textColorLight)); nextUnlockTextView.setText(message); Button confirmButton = (Button) view.findViewById(R.id.confirm_button); + confirmButton.setTextColor(ContextCompat.getColor(context, R.color.brand_300)); - AlertDialog.Builder builder = new AlertDialog.Builder(HabiticaApplication.currentActivity) + AlertDialog.Builder builder = new AlertDialog.Builder(HabiticaApplication.currentActivity, R.style.AlertDialogTheme) .setTitle(title) .setView(view) .setMessage(""); From 3f15d04765f57783a1f9e83d553aeaabc8af081b Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Wed, 19 Apr 2017 16:54:44 +0200 Subject: [PATCH 06/29] bump build number --- Habitica/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Habitica/AndroidManifest.xml b/Habitica/AndroidManifest.xml index dce904f2a..fbc0841a3 100644 --- a/Habitica/AndroidManifest.xml +++ b/Habitica/AndroidManifest.xml @@ -2,7 +2,7 @@ From 03fa5162077432e431d363110bccd450d23999fa Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Wed, 19 Apr 2017 17:22:42 +0200 Subject: [PATCH 07/29] fix test setup --- .../java/com/habitrpg/android/habitica/api/BaseAPITests.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Habitica/src/test/java/com/habitrpg/android/habitica/api/BaseAPITests.java b/Habitica/src/test/java/com/habitrpg/android/habitica/api/BaseAPITests.java index 8f12f6666..e0334b7a5 100644 --- a/Habitica/src/test/java/com/habitrpg/android/habitica/api/BaseAPITests.java +++ b/Habitica/src/test/java/com/habitrpg/android/habitica/api/BaseAPITests.java @@ -2,6 +2,7 @@ package com.habitrpg.android.habitica.api; import com.habitrpg.android.habitica.data.implementation.ApiClientImpl; +import com.habitrpg.android.habitica.helpers.PopupNotificationsManager; import com.habitrpg.android.habitica.proxy.impl.EmptyCrashlyticsProxy; import com.habitrpg.android.habitica.data.ApiClient; import com.habitrpg.android.habitica.BuildConfig; @@ -39,7 +40,7 @@ public class BaseAPITests { BuildConfig.PORT, "", ""); - apiClient = new ApiClientImpl(ApiClientImpl.createGsonFactory(), hostConfig, new EmptyCrashlyticsProxy(), context); + apiClient = new ApiClientImpl(ApiClientImpl.createGsonFactory(), hostConfig, new EmptyCrashlyticsProxy(), new PopupNotificationsManager(context), context); generateUser(); } From 05e281729367ae0385ab8efe4042f2e3c52a767b Mon Sep 17 00:00:00 2001 From: Negue Date: Wed, 19 Apr 2017 20:57:44 +0200 Subject: [PATCH 08/29] Parcelable Task / Days --- .../lib/models/tasks/Days.java | 45 +++++++++- .../lib/models/tasks/Task.java | 83 ++++++++++++++++++- 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/tasks/Days.java b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/tasks/Days.java index b420481c2..afc88cf96 100644 --- a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/tasks/Days.java +++ b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/tasks/Days.java @@ -1,5 +1,8 @@ package com.magicmicky.habitrpgwrapper.lib.models.tasks; +import android.os.Parcel; +import android.os.Parcelable; + import com.habitrpg.android.habitica.HabitDatabase; import com.raizlabs.android.dbflow.annotation.Column; import com.raizlabs.android.dbflow.annotation.ModelContainer; @@ -13,7 +16,7 @@ import com.raizlabs.android.dbflow.structure.BaseModel; */ @ModelContainer @Table(databaseName = HabitDatabase.NAME) -public class Days extends BaseModel { +public class Days extends BaseModel implements Parcelable { @Column @PrimaryKey @@ -108,4 +111,44 @@ public class Days extends BaseModel { } return false; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.task_id); + dest.writeByte(this.m ? (byte) 1 : (byte) 0); + dest.writeByte(this.t ? (byte) 1 : (byte) 0); + dest.writeByte(this.w ? (byte) 1 : (byte) 0); + dest.writeByte(this.th ? (byte) 1 : (byte) 0); + dest.writeByte(this.f ? (byte) 1 : (byte) 0); + dest.writeByte(this.s ? (byte) 1 : (byte) 0); + dest.writeByte(this.su ? (byte) 1 : (byte) 0); + } + + protected Days(Parcel in) { + this.task_id = in.readString(); + this.m = in.readByte() != 0; + this.t = in.readByte() != 0; + this.w = in.readByte() != 0; + this.th = in.readByte() != 0; + this.f = in.readByte() != 0; + this.s = in.readByte() != 0; + this.su = in.readByte() != 0; + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public Days createFromParcel(Parcel source) { + return new Days(source); + } + + @Override + public Days[] newArray(int size) { + return new Days[size]; + } + }; } diff --git a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/tasks/Task.java b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/tasks/Task.java index 1ec9ba3c9..319138eca 100644 --- a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/tasks/Task.java +++ b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/tasks/Task.java @@ -19,6 +19,8 @@ import com.raizlabs.android.dbflow.structure.BaseModel; import org.greenrobot.eventbus.EventBus; +import android.os.Parcel; +import android.os.Parcelable; import android.support.annotation.Nullable; import java.util.ArrayList; @@ -33,7 +35,7 @@ import java.util.concurrent.TimeUnit; */ @ModelContainer @Table(databaseName = HabitDatabase.NAME) -public class Task extends BaseModel { +public class Task extends BaseModel implements Parcelable { public static final String TYPE_HABIT = "habit"; public static final String TYPE_TODO = "todo"; public static final String TYPE_DAILY = "daily"; @@ -668,4 +670,83 @@ public class Task extends BaseModel { } return false; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.user_id); + dest.writeValue(this.priority); + dest.writeString(this.text); + dest.writeString(this.notes); + dest.writeString(this.attribute); + dest.writeString(this.type); + dest.writeDouble(this.value); + dest.writeList(this.tags); + dest.writeLong(this.dateCreated != null ? this.dateCreated.getTime() : -1); + dest.writeInt(this.position); + dest.writeValue(this.up); + dest.writeValue(this.down); + dest.writeByte(this.completed ? (byte) 1 : (byte) 0); + dest.writeList(this.checklist); + dest.writeList(this.reminders); + dest.writeString(this.frequency); + dest.writeValue(this.everyX); + dest.writeValue(this.streak); + dest.writeLong(this.startDate != null ? this.startDate.getTime() : -1); + dest.writeParcelable(this.repeat, flags); + dest.writeLong(this.duedate != null ? this.duedate.getTime() : -1); + dest.writeString(this.specialTag); + dest.writeString(this.id); + } + + public Task() { + } + + protected Task(Parcel in) { + this.user_id = in.readString(); + this.priority = (Float) in.readValue(Float.class.getClassLoader()); + this.text = in.readString(); + this.notes = in.readString(); + this.attribute = in.readString(); + this.type = in.readString(); + this.value = in.readDouble(); + this.tags = new ArrayList(); + in.readList(this.tags, TaskTag.class.getClassLoader()); + long tmpDateCreated = in.readLong(); + this.dateCreated = tmpDateCreated == -1 ? null : new Date(tmpDateCreated); + this.position = in.readInt(); + this.up = (Boolean) in.readValue(Boolean.class.getClassLoader()); + this.down = (Boolean) in.readValue(Boolean.class.getClassLoader()); + this.completed = in.readByte() != 0; + this.checklist = new ArrayList(); + in.readList(this.checklist, ChecklistItem.class.getClassLoader()); + this.reminders = new ArrayList(); + in.readList(this.reminders, RemindersItem.class.getClassLoader()); + this.frequency = in.readString(); + this.everyX = (Integer) in.readValue(Integer.class.getClassLoader()); + this.streak = (Integer) in.readValue(Integer.class.getClassLoader()); + long tmpStartDate = in.readLong(); + this.startDate = tmpStartDate == -1 ? null : new Date(tmpStartDate); + this.repeat = in.readParcelable(Days.class.getClassLoader()); + long tmpDuedate = in.readLong(); + this.duedate = tmpDuedate == -1 ? null : new Date(tmpDuedate); + this.specialTag = in.readString(); + this.id = in.readString(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public Task createFromParcel(Parcel source) { + return new Task(source); + } + + @Override + public Task[] newArray(int size) { + return new Task[size]; + } + }; } From 722fe0673e86866b31cf5a5e1a9ec808698e41b6 Mon Sep 17 00:00:00 2001 From: Negue Date: Wed, 19 Apr 2017 21:00:42 +0200 Subject: [PATCH 09/29] open TaskFormActivity with a PARCELABLE_TASK (to edit unsaved tasks) --- .../ui/activities/TaskFormActivity.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java index 66f390344..d8263f65c 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java @@ -87,6 +87,8 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem public static final String TASK_ID_KEY = "taskId"; public static final String USER_ID_KEY = "userId"; public static final String TASK_TYPE_KEY = "type"; + public static final String SHOW_TAG_SELECTION = "show_tag_selection"; + public static final String PARCELABLE_TASK = "parcelable_task"; public static final String ALLOCATION_MODE_KEY = "allocationModeKey"; public static final String SAVE_TO_DB = "saveToDb"; @@ -202,6 +204,7 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem private String taskType; private String taskId; private String userId; + private boolean showTagSelection; private Task task; private String allocationMode; private List weekdayCheckboxes = new ArrayList<>(); @@ -228,11 +231,21 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem Intent intent = getIntent(); Bundle bundle = intent.getExtras(); + taskType = bundle.getString(TASK_TYPE_KEY); taskId = bundle.getString(TASK_ID_KEY); userId = bundle.getString(USER_ID_KEY); + showTagSelection = bundle.getBoolean(SHOW_TAG_SELECTION, true); allocationMode = bundle.getString(ALLOCATION_MODE_KEY); saveToDb = bundle.getBoolean(SAVE_TO_DB, true); + + tagsWrapper.setVisibility(showTagSelection ? View.VISIBLE : View.GONE); + + if(bundle.containsKey(PARCELABLE_TASK)){ + task = bundle.getParcelable(PARCELABLE_TASK); + taskType = task.type; + } + tagCheckBoxList = new ArrayList<>(); selectedTags = new ArrayList<>(); if (taskType == null) { @@ -257,7 +270,13 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem finish(); dismissKeyboard(); - EventBus.getDefault().post(new DeleteTaskCommand(taskId)); + String taskToDelete = this.taskId; + + if(taskToDelete == null && task != null){ + taskToDelete = task.getId(); + } + + EventBus.getDefault().post(new DeleteTaskCommand(taskToDelete)); }).setNegativeButton(getString(R.string.no), (dialog, which) -> { dialog.dismiss(); }).show()); @@ -335,6 +354,11 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem setTitle(task); + btnDelete.setEnabled(true); + } else if(task != null) { + populate(task); + taskText.requestFocus(); + btnDelete.setEnabled(true); } else { setTitle((Task) null); From 82007a5f8930c740d878ba0cb3fe73d6dc5e5b62 Mon Sep 17 00:00:00 2001 From: Negue Date: Wed, 19 Apr 2017 21:01:55 +0200 Subject: [PATCH 10/29] add / edit / remove tasks --- Habitica/res/values/strings.xml | 1 + .../activities/CreateChallengeActivity.java | 96 ++++++++++++++----- .../ChallengeTasksRecyclerViewAdapter.java | 10 ++ .../tasks/BaseTasksRecyclerViewAdapter.java | 14 ++- 4 files changed, 93 insertions(+), 28 deletions(-) diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml index da44076b2..0c08a6010 100644 --- a/Habitica/res/values/strings.xml +++ b/Habitica/res/values/strings.xml @@ -560,4 +560,5 @@ Location Gem reward Tasks + Create challenge diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java index 0e18992b2..1f5fdd3e9 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java @@ -5,7 +5,6 @@ import android.content.res.Resources; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.support.v7.app.ActionBar; -import android.support.v7.view.menu.MenuAdapter; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.Menu; @@ -18,8 +17,9 @@ import com.habitrpg.android.habitica.HabiticaApplication; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.components.AppComponent; import com.habitrpg.android.habitica.events.TaskSaveEvent; +import com.habitrpg.android.habitica.events.TaskTappedEvent; +import com.habitrpg.android.habitica.events.commands.DeleteTaskCommand; import com.habitrpg.android.habitica.ui.adapter.social.challenges.ChallengeTasksRecyclerViewAdapter; -import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeTasksRecyclerViewFragment; import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task; import org.greenrobot.eventbus.EventBus; @@ -39,7 +39,14 @@ public class CreateChallengeActivity extends BaseActivity { @BindView(R.id.create_challenge_task_list) RecyclerView create_challenge_task_list; - private boolean displayingTaskForm; + private ChallengeTasksRecyclerViewAdapter challengeTasks; + + + Task addHabit; + Task addDaily; + Task addTodo; + Task addReward; + @Override protected int getLayoutResId() { @@ -65,6 +72,7 @@ public class CreateChallengeActivity extends BaseActivity { if (supportActionBar != null) { supportActionBar.setIcon(R.drawable.ic_close_white_24dp); + supportActionBar.setTitle(R.string.create_challenge); supportActionBar.setBackgroundDrawable(new ColorDrawable(resources.getColor(R.color.brand_200))); supportActionBar.setElevation(0); } @@ -74,34 +82,28 @@ public class CreateChallengeActivity extends BaseActivity { locationAdapter.addAll("Tavern", "My Group", "Some other"); challenge_location_spinner.setAdapter(locationAdapter); - Task addHabit = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_habit)); - Task addDaily = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_daily)); - Task addTodo = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_todo)); - Task addReward = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_reward)); + addHabit = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_habit)); + addDaily = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_daily)); + addTodo = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_todo)); + addReward = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_reward)); + ArrayList taskList = new ArrayList<>(); taskList.add(addHabit); - taskList.add(createTask(Task.TYPE_HABIT)); taskList.add(addDaily); - taskList.add(createTask(Task.TYPE_DAILY)); taskList.add(addTodo); - taskList.add(createTask(Task.TYPE_TODO)); taskList.add(addReward); - taskList.add(createTask(Task.TYPE_REWARD)); - ChallengeTasksRecyclerViewAdapter challengeTasks = new ChallengeTasksRecyclerViewAdapter(null, 0, this, "", null, false, true); + challengeTasks = new ChallengeTasksRecyclerViewAdapter(null, 0, this, "", null, false, true); challengeTasks.setTasks(taskList); challengeTasks.enableAddItem(t -> { if (t.equals(addHabit)) { openNewTaskActivity(Task.TYPE_HABIT); } else if (t.equals(addDaily)) { - openNewTaskActivity(Task.TYPE_DAILY); } else if (t.equals(addTodo)) { - openNewTaskActivity(Task.TYPE_TODO); } else if (t.equals(addReward)) { - openNewTaskActivity(Task.TYPE_REWARD); } }); @@ -119,13 +121,10 @@ public class CreateChallengeActivity extends BaseActivity { } private void openNewTaskActivity(String type) { - if (this.displayingTaskForm) { - return; - } - Bundle bundle = new Bundle(); bundle.putString(TaskFormActivity.TASK_TYPE_KEY, type); bundle.putBoolean(TaskFormActivity.SAVE_TO_DB, false); + bundle.putBoolean(TaskFormActivity.SHOW_TAG_SELECTION, false); if (HabiticaApplication.User != null && HabiticaApplication.User.getPreferences() != null) { String allocationMode = HabiticaApplication.User.getPreferences().getAllocationMode(); @@ -134,26 +133,73 @@ public class CreateChallengeActivity extends BaseActivity { bundle.putString(TaskFormActivity.ALLOCATION_MODE_KEY, allocationMode); } + Intent intent = new Intent(this, TaskFormActivity.class); + intent.putExtras(bundle); + intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + + startActivityForResult(intent, 1); + } + + private void openNewTaskActivity(Task task) { + Bundle bundle = new Bundle(); + bundle.putParcelable(TaskFormActivity.PARCELABLE_TASK, task); + bundle.putBoolean(TaskFormActivity.SAVE_TO_DB, false); + bundle.putBoolean(TaskFormActivity.SHOW_TAG_SELECTION, false); + + if (HabiticaApplication.User != null && HabiticaApplication.User.getPreferences() != null) { + String allocationMode = HabiticaApplication.User.getPreferences().getAllocationMode(); + + bundle.putString(TaskFormActivity.USER_ID_KEY, HabiticaApplication.User.getId()); + bundle.putString(TaskFormActivity.ALLOCATION_MODE_KEY, allocationMode); + } Intent intent = new Intent(this, TaskFormActivity.class); intent.putExtras(bundle); intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - this.displayingTaskForm = true; startActivityForResult(intent, 1); } @Subscribe - public void onEvent(TaskSaveEvent saveEvent) + public void onEvent(DeleteTaskCommand deleteTask){ + challengeTasks.removeTask(deleteTask.TaskIdToDelete); + } + + @Subscribe + public void onEvent(TaskTappedEvent tappedEvent) { - + openNewTaskActivity(tappedEvent.Task); } - private Task createTask(String taskType) { - return createTask(taskType, "example " + taskType); + @Subscribe + public void onEvent(TaskSaveEvent saveEvent) { + + if(saveEvent.task.getId() == null) + saveEvent.task.setId(UUID.randomUUID().toString()); + + if (!challengeTasks.updateTask(saveEvent.task)) { + Task taskAbove; + + switch (saveEvent.task.getType()) { + case Task.TYPE_HABIT: + taskAbove = addHabit; + break; + case Task.TYPE_DAILY: + taskAbove = addDaily; + break; + case Task.TYPE_TODO: + taskAbove = addTodo; + break; + default: + taskAbove = addReward; + break; + } + + challengeTasks.addTaskUnder(saveEvent.task, taskAbove); + } } - private Task createTask(String taskType, String taskName) { + private static Task createTask(String taskType, String taskName) { Task t = new Task(); t.setId(UUID.randomUUID().toString()); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/challenges/ChallengeTasksRecyclerViewAdapter.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/challenges/ChallengeTasksRecyclerViewAdapter.java index 7578535a4..e7e9fc044 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/challenges/ChallengeTasksRecyclerViewAdapter.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/challenges/ChallengeTasksRecyclerViewAdapter.java @@ -7,6 +7,7 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; +import com.github.underscore.$; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.components.AppComponent; import com.habitrpg.android.habitica.helpers.TaskFilterHelper; @@ -83,6 +84,15 @@ public class ChallengeTasksRecyclerViewAdapter extends SortableTasksRecyclerView addItemCallback = cb; } + public int addTaskUnder(Task taskToAdd, Task taskAbove){ + int position = $.findIndex(this.content, t -> t.getId().equals(taskAbove.getId())); + + content.add(position+1, taskToAdd); + filter(); + + return position; + } + @Override public BaseTaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { BaseTaskViewHolder viewHolder = null; diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/BaseTasksRecyclerViewAdapter.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/BaseTasksRecyclerViewAdapter.java index e7f239bfb..20cab3d2f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/BaseTasksRecyclerViewAdapter.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/tasks/BaseTasksRecyclerViewAdapter.java @@ -90,9 +90,13 @@ public abstract class BaseTasksRecyclerViewAdapter Date: Thu, 20 Apr 2017 00:29:45 +0200 Subject: [PATCH 11/29] save groups to database --- .../android/habitica/HabitDatabase.java | 2 +- .../data/local/ChallengeLocalRepository.java | 13 +++++ .../DbFlowChallengeLocalRepository.java | 58 +++++++++++++++++++ .../habitica/modules/RepositoryModule.java | 7 +++ .../social/GuildsOverviewFragment.java | 8 +++ .../habitrpgwrapper/lib/models/Group.java | 27 +++++++-- 6 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/DbFlowChallengeLocalRepository.java diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/HabitDatabase.java b/Habitica/src/main/java/com/habitrpg/android/habitica/HabitDatabase.java index 4be466de1..56ed150b8 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/HabitDatabase.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/HabitDatabase.java @@ -7,7 +7,7 @@ public class HabitDatabase { public static final String NAME = "Habitica"; - public static final int VERSION = 35; + public static final int VERSION = 36; public HabitDatabase() { super(); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.java new file mode 100644 index 000000000..ec2b1a3ac --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ChallengeLocalRepository.java @@ -0,0 +1,13 @@ +package com.habitrpg.android.habitica.data.local; + +import com.magicmicky.habitrpgwrapper.lib.models.Group; +import java.util.List; + +import rx.Observable; + +public interface ChallengeLocalRepository extends BaseLocalRepository { + + void setUsersGroups(List group); + + Observable> getGroups(); +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/DbFlowChallengeLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/DbFlowChallengeLocalRepository.java new file mode 100644 index 000000000..a71e19e8f --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/DbFlowChallengeLocalRepository.java @@ -0,0 +1,58 @@ +package com.habitrpg.android.habitica.data.local.implementation; + +import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository; +import com.magicmicky.habitrpgwrapper.lib.models.Group; +import com.raizlabs.android.dbflow.runtime.transaction.BaseTransaction; +import com.raizlabs.android.dbflow.runtime.transaction.TransactionListener; +import com.raizlabs.android.dbflow.sql.builder.Condition; +import com.raizlabs.android.dbflow.sql.language.Delete; +import com.raizlabs.android.dbflow.sql.language.Select; + +import java.util.List; + +import rx.Observable; + +public class DbFlowChallengeLocalRepository implements ChallengeLocalRepository { + + + @Override + public void setUsersGroups(List groups) { + + new Delete().from(Group.class).query(); + + + for (Group group : groups) { + group.isMember = true; + group.async().save(); + } + } + + @Override + public Observable> getGroups() { + return Observable.create(subscriber -> { + new Select().from(Group.class).where(Condition.column("isMember").is(true)).async().queryList(new TransactionListener>() { + @Override + public void onResultReceived(List result) { + subscriber.onNext(result); + subscriber.onCompleted(); + } + + @Override + public boolean onReady(BaseTransaction> transaction) { + return false; + } + + @Override + public boolean hasResult(BaseTransaction> transaction, List result) { + return true; + } + }); + }); + } + + + @Override + public void close() { + + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java index 1cb1128dd..1d426b88f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java @@ -7,8 +7,10 @@ import com.habitrpg.android.habitica.data.TaskRepository; import com.habitrpg.android.habitica.data.implementation.SetupCustomizationRepositoryImpl; import com.habitrpg.android.habitica.data.implementation.TagRepositoryImpl; import com.habitrpg.android.habitica.data.implementation.TaskRepositoryImpl; +import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository; import com.habitrpg.android.habitica.data.local.TagLocalRepository; import com.habitrpg.android.habitica.data.local.TaskLocalRepository; +import com.habitrpg.android.habitica.data.local.implementation.DbFlowChallengeLocalRepository; import com.habitrpg.android.habitica.data.local.implementation.DbFlowTaskLocalRepository; import com.habitrpg.android.habitica.data.local.implementation.TagLocalRepositoryImpl; import com.magicmicky.habitrpgwrapper.lib.api.ApiClient; @@ -29,6 +31,11 @@ public class RepositoryModule { } + @Provides + ChallengeLocalRepository provideChallengeLocalRepository(){ + return new DbFlowChallengeLocalRepository(); + } + @Provides TaskLocalRepository providesTaskLocalRepository() { return new DbFlowTaskLocalRepository(); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.java index 42273c28a..01991928c 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/GuildsOverviewFragment.java @@ -2,6 +2,7 @@ package com.habitrpg.android.habitica.ui.fragments.social; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.components.AppComponent; +import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository; import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment; import com.magicmicky.habitrpgwrapper.lib.models.Group; @@ -18,6 +19,8 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.List; +import javax.inject.Inject; + import butterknife.BindView; import butterknife.ButterKnife; @@ -32,6 +35,9 @@ public class GuildsOverviewFragment extends BaseMainFragment implements View.OnC @BindView(R.id.chat_refresh_layout) SwipeRefreshLayout swipeRefreshLayout; + @Inject + ChallengeLocalRepository challengeLocalRepository; + private List guilds; private ArrayList guildIDs; @@ -77,6 +83,8 @@ public class GuildsOverviewFragment extends BaseMainFragment implements View.OnC if (swipeRefreshLayout != null) { swipeRefreshLayout.setRefreshing(false); } + + challengeLocalRepository.setUsersGroups(groups); }, throwable -> { }); } diff --git a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/Group.java b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/Group.java index fc4950dd5..f68995111 100644 --- a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/Group.java +++ b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/Group.java @@ -2,51 +2,66 @@ package com.magicmicky.habitrpgwrapper.lib.models; import com.google.gson.annotations.SerializedName; +import com.habitrpg.android.habitica.HabitDatabase; +import com.raizlabs.android.dbflow.annotation.Column; +import com.raizlabs.android.dbflow.annotation.NotNull; +import com.raizlabs.android.dbflow.annotation.PrimaryKey; +import com.raizlabs.android.dbflow.annotation.Table; import com.raizlabs.android.dbflow.structure.BaseModel; import java.util.List; -/** - * Created by Negue on 16.09.2015. - */ +@Table(databaseName = HabitDatabase.NAME, tableName = "_group") public class Group extends BaseModel { + @Column + @PrimaryKey + @NotNull @SerializedName("_id") public String id; + @Column public double balance; + @Column public String description; + @Column public String leaderID; + @Column public String leaderName; + @Column public String name; + @Column public int memberCount; + @Column public Boolean isMember; + @Column public String type; + @Column public String logo; public Quest quest; public String privacy; + public List chat; public List members; + @Column public int challengeCount; + @Column public String leaderMessage; - // TODO Challenges - - @Override public boolean equals(Object o) { if (this == o) { From b4e8b951164262e09948c62f9308cada0e9d35e5 Mon Sep 17 00:00:00 2001 From: Negue Date: Thu, 20 Apr 2017 00:31:47 +0200 Subject: [PATCH 12/29] Navigation ChallengeList -> CreateChallenge / list possible challenge locations --- .../res/layout/fragment_challengeslist.xml | 92 ++++++++++--------- Habitica/res/menu/menu_list_challenges.xml | 10 ++ Habitica/res/values/strings.xml | 1 + .../habitica/HabiticaBaseApplication.java | 3 +- .../activities/CreateChallengeActivity.java | 50 +++++++++- .../challenges/ChallengeListFragment.java | 39 +++++++- 6 files changed, 140 insertions(+), 55 deletions(-) create mode 100644 Habitica/res/menu/menu_list_challenges.xml diff --git a/Habitica/res/layout/fragment_challengeslist.xml b/Habitica/res/layout/fragment_challengeslist.xml index 7819e15a7..a8a5e2b65 100644 --- a/Habitica/res/layout/fragment_challengeslist.xml +++ b/Habitica/res/layout/fragment_challengeslist.xml @@ -1,4 +1,4 @@ - @@ -54,62 +55,65 @@ android:scrollbars="vertical" android:paddingBottom="?attr/actionBarSize" /> - - + + + android:layout_height="wrap_content" + android:layout_marginLeft="48dp" + android:layout_marginRight="48dp" + android:layout_marginTop="65dp" + android:orientation="vertical"> - + android:layout_height="match_parent" + android:gravity="center" + android:maxLines="2" + android:text="@string/not_part_of_a_challenge" + android:textAlignment="center" + android:textColor="#8a000000" /> - + - + - + - - - + - \ No newline at end of file + + + \ No newline at end of file diff --git a/Habitica/res/menu/menu_list_challenges.xml b/Habitica/res/menu/menu_list_challenges.xml new file mode 100644 index 000000000..1b553db6a --- /dev/null +++ b/Habitica/res/menu/menu_list_challenges.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml index 0c08a6010..e0468301b 100644 --- a/Habitica/res/values/strings.xml +++ b/Habitica/res/values/strings.xml @@ -561,4 +561,5 @@ Gem reward Tasks Create challenge + Tavern diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaBaseApplication.java b/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaBaseApplication.java index e1f5b6883..ec9a42013 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaBaseApplication.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaBaseApplication.java @@ -120,8 +120,7 @@ public abstract class HabiticaBaseApplication extends MultiDexApplication { } public static boolean checkUserAuthentication(Context context, HostConfig hostConfig) { - startActivity(CreateChallengeActivity.class, context); - + //startActivity(CreateChallengeActivity.class, context); if (hostConfig == null || hostConfig.getApi() == null || hostConfig.getApi().equals("") || hostConfig.getUser() == null || hostConfig.getUser().equals("")) { startActivity(IntroActivity.class, context); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java index 1f5fdd3e9..29b412aae 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/CreateChallengeActivity.java @@ -1,25 +1,34 @@ package com.habitrpg.android.habitica.ui.activities; +import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v7.app.ActionBar; +import android.support.v7.widget.AppCompatCheckedTextView; +import android.support.v7.widget.AppCompatTextView; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.Menu; import android.view.MenuInflater; import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Spinner; import com.habitrpg.android.habitica.HabiticaApplication; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.components.AppComponent; +import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository; import com.habitrpg.android.habitica.events.TaskSaveEvent; import com.habitrpg.android.habitica.events.TaskTappedEvent; import com.habitrpg.android.habitica.events.commands.DeleteTaskCommand; import com.habitrpg.android.habitica.ui.adapter.social.challenges.ChallengeTasksRecyclerViewAdapter; +import com.magicmicky.habitrpgwrapper.lib.models.Group; import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task; import org.greenrobot.eventbus.EventBus; @@ -28,6 +37,8 @@ import org.greenrobot.eventbus.Subscribe; import java.util.ArrayList; import java.util.UUID; +import javax.inject.Inject; + import butterknife.BindView; public class CreateChallengeActivity extends BaseActivity { @@ -39,8 +50,10 @@ public class CreateChallengeActivity extends BaseActivity { @BindView(R.id.create_challenge_task_list) RecyclerView create_challenge_task_list; - private ChallengeTasksRecyclerViewAdapter challengeTasks; + @Inject + ChallengeLocalRepository challengeLocalRepository; + private ChallengeTasksRecyclerViewAdapter challengeTasks; Task addHabit; Task addDaily; @@ -77,9 +90,18 @@ public class CreateChallengeActivity extends BaseActivity { supportActionBar.setElevation(0); } - ArrayAdapter locationAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item); + GroupArrayAdapter locationAdapter = new GroupArrayAdapter(this); locationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - locationAdapter.addAll("Tavern", "My Group", "Some other"); + challengeLocalRepository.getGroups().subscribe(groups -> { + Group tavern =new Group(); + tavern.id = "habitrpg"; + tavern.name = getString(R.string.tavern); + + locationAdapter.add(tavern); + + groups.forEach(group -> locationAdapter.add(group)); + }, Throwable::printStackTrace); + challenge_location_spinner.setAdapter(locationAdapter); addHabit = createTask(ChallengeTasksRecyclerViewAdapter.TASK_TYPE_ADD_ITEM, resources.getString(R.string.add_habit)); @@ -117,7 +139,6 @@ public class CreateChallengeActivity extends BaseActivity { }); create_challenge_task_list.setAdapter(challengeTasks); create_challenge_task_list.setLayoutManager(new LinearLayoutManager(this)); - } private void openNewTaskActivity(String type) { @@ -219,4 +240,25 @@ public class CreateChallengeActivity extends BaseActivity { protected void injectActivity(AppComponent component) { component.inject(this); } + + private class GroupArrayAdapter extends ArrayAdapter { + public GroupArrayAdapter(@NonNull Context context) { + super(context, android.R.layout.simple_spinner_item); + } + + @NonNull + @Override + public View getView(int position, View convertView, ViewGroup parent) { + AppCompatTextView checkedTextView = (AppCompatTextView) super.getView(position, convertView, parent); + checkedTextView.setText(getItem(position).name); + return checkedTextView; + } + + @Override + public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { + AppCompatCheckedTextView checkedTextView = (AppCompatCheckedTextView) super.getDropDownView(position, convertView, parent); + checkedTextView.setText(getItem(position).name); + return checkedTextView; + } + } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.java index 7b083e820..4db1af389 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeListFragment.java @@ -1,17 +1,23 @@ package com.habitrpg.android.habitica.ui.fragments.social.challenges; +import android.content.Intent; import android.os.Bundle; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.components.AppComponent; +import com.habitrpg.android.habitica.ui.activities.CreateChallengeActivity; +import com.habitrpg.android.habitica.ui.activities.PartyInviteActivity; import com.habitrpg.android.habitica.ui.adapter.social.ChallengesListViewAdapter; import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment; import com.magicmicky.habitrpgwrapper.lib.models.Challenge; @@ -50,7 +56,7 @@ public class ChallengeListFragment extends BaseMainFragment implements SwipeRefr private Action0 refreshCallback; private boolean withFilter; - public void setWithFilter(boolean withFilter){ + public void setWithFilter(boolean withFilter) { this.withFilter = withFilter; } @@ -121,12 +127,12 @@ public class ChallengeListFragment extends BaseMainFragment implements SwipeRefr swipeRefreshLayout.setOnRefreshListener(this); swipeRefreshEmptyLayout.setOnRefreshListener(this); - challengeFilterLayout.setVisibility(withFilter?View.VISIBLE:View.GONE); + challengeFilterLayout.setVisibility(withFilter ? View.VISIBLE : View.GONE); challengeFilterLayout.setClickable(true); challengeFilterLayout.setOnClickListener(view -> ChallengeFilterDialogHolder.showDialog(getActivity(), currentChallengesInView, lastFilterOptions, filterOptions -> { - challengeAdapter.setFilterByGroups(filterOptions); - this.lastFilterOptions = filterOptions; - })); + challengeAdapter.setFilterByGroups(filterOptions); + this.lastFilterOptions = filterOptions; + })); recyclerView.setLayoutManager(new LinearLayoutManager(this.activity)); recyclerView.setAdapter(challengeAdapter); @@ -215,4 +221,27 @@ public class ChallengeListFragment extends BaseMainFragment implements SwipeRefr public String customTitle() { return getString(R.string.sidebar_challenges); } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.menu_list_challenges, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + + switch (id) { + case R.id.action_create_challenge: + Intent intent = new Intent(getActivity(), CreateChallengeActivity.class); + startActivity(intent); + + return true; + } + + return super.onOptionsItemSelected(item); + } } From 9e74288f2df7a6394c04cc321b26a7b9cd64f581 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Thu, 20 Apr 2017 11:00:59 +0200 Subject: [PATCH 13/29] Fix fab handling when scrolled away --- Habitica/res/anim/fab_slide_in.xml | 7 +++++-- Habitica/res/anim/fab_slide_out.xml | 7 +++++-- Habitica/res/layout/floating_menu_tasks.xml | 4 +++- .../ui/helpers/FloatingActionMenuBehavior.java | 11 ++--------- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Habitica/res/anim/fab_slide_in.xml b/Habitica/res/anim/fab_slide_in.xml index 1675a9ae1..bac34df5b 100644 --- a/Habitica/res/anim/fab_slide_in.xml +++ b/Habitica/res/anim/fab_slide_in.xml @@ -1,4 +1,7 @@ - - + + \ No newline at end of file diff --git a/Habitica/res/anim/fab_slide_out.xml b/Habitica/res/anim/fab_slide_out.xml index b82f4d744..6d97fbbe2 100644 --- a/Habitica/res/anim/fab_slide_out.xml +++ b/Habitica/res/anim/fab_slide_out.xml @@ -1,4 +1,7 @@ - - + + \ No newline at end of file diff --git a/Habitica/res/layout/floating_menu_tasks.xml b/Habitica/res/layout/floating_menu_tasks.xml index c237864d0..9485d17a9 100644 --- a/Habitica/res/layout/floating_menu_tasks.xml +++ b/Habitica/res/layout/floating_menu_tasks.xml @@ -18,7 +18,9 @@ fab:menu_animationDelayPerItem="50" fab:menu_icon="@drawable/fab_add" fab:menu_buttonSpacing="2dp" - fab:menu_labels_margin="4dp"> + fab:menu_labels_margin="4dp" + fab:menu_fab_show_animation="@anim/fab_slide_in" + fab:menu_fab_hide_animation="@anim/fab_slide_out"> Date: Thu, 20 Apr 2017 20:04:31 +0200 Subject: [PATCH 14/29] Create / Update / Delete Challenge API-Routes --- .../android/habitica/ApiClientImpl.java | 17 ++++++++++ .../habitica/data/ChallengeRepository.java | 12 +++++++ .../ChallengeRepositoryImpl.java | 32 +++++++++++++++++++ .../habitica/modules/RepositoryModule.java | 10 ++++++ .../habitrpgwrapper/lib/api/ApiClient.java | 5 +++ .../habitrpgwrapper/lib/api/ApiService.java | 11 +++++++ .../lib/models/PostChallenge.java | 25 +++++++++++++++ 7 files changed, 112 insertions(+) create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.java create mode 100644 Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/PostChallenge.java diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ApiClientImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ApiClientImpl.java index a01d208ad..91b34a6f1 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ApiClientImpl.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ApiClientImpl.java @@ -25,6 +25,7 @@ import com.magicmicky.habitrpgwrapper.lib.models.Group; import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser; import com.magicmicky.habitrpgwrapper.lib.models.Items; import com.magicmicky.habitrpgwrapper.lib.models.LeaveChallengeBody; +import com.magicmicky.habitrpgwrapper.lib.models.PostChallenge; import com.magicmicky.habitrpgwrapper.lib.models.PostChatMessageResult; import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationRequest; import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationResult; @@ -811,6 +812,22 @@ public class ApiClientImpl implements Action1, ApiClient { return apiService.leaveChallenge(challengeId, body).compose(configureApiCallObserver()); } + + @Override + public Observable createChallenge(PostChallenge challenge){ + return apiService.createChallenge(challenge).compose(configureApiCallObserver()); + } + + @Override + public Observable updateChallenge(PostChallenge challenge){ + return apiService.updateChallenge(challenge.id, challenge).compose(configureApiCallObserver()); + } + + @Override + public Observable deleteChallenge(String challengeId){ + return apiService.deleteChallenge(challengeId).compose(configureApiCallObserver()); + } + @Override public Observable debugAddTenGems() { return apiService.debugAddTenGems().compose(configureApiCallObserver()); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.java new file mode 100644 index 000000000..f67a7796f --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.java @@ -0,0 +1,12 @@ +package com.habitrpg.android.habitica.data; + +import com.magicmicky.habitrpgwrapper.lib.models.Challenge; +import com.magicmicky.habitrpgwrapper.lib.models.PostChallenge; + +import rx.Observable; + +public interface ChallengeRepository extends BaseRepository { + Observable createChallenge(PostChallenge challenge); + Observable updateChallenge(PostChallenge challenge); + Observable deleteChallenge(String challengeId); +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.java new file mode 100644 index 000000000..6db933420 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.java @@ -0,0 +1,32 @@ +package com.habitrpg.android.habitica.data.implementation; + +import com.habitrpg.android.habitica.data.ChallengeRepository; +import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository; +import com.magicmicky.habitrpgwrapper.lib.api.ApiClient; +import com.magicmicky.habitrpgwrapper.lib.models.Challenge; +import com.magicmicky.habitrpgwrapper.lib.models.PostChallenge; + +import rx.Observable; + + +public class ChallengeRepositoryImpl extends BaseRepositoryImpl implements ChallengeRepository { + + public ChallengeRepositoryImpl(ChallengeLocalRepository localRepository, ApiClient apiClient) { + super(localRepository, apiClient); + } + + @Override + public Observable createChallenge(PostChallenge challenge) { + return apiClient.createChallenge(challenge); + } + + @Override + public Observable updateChallenge(PostChallenge challenge) { + return apiClient.updateChallenge(challenge); + } + + @Override + public Observable deleteChallenge(String challengeId) { + return apiClient.deleteChallenge(challengeId); + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java index 1d426b88f..63e7338b1 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/RepositoryModule.java @@ -1,9 +1,11 @@ package com.habitrpg.android.habitica.modules; +import com.habitrpg.android.habitica.data.ChallengeRepository; import com.habitrpg.android.habitica.data.SetupCustomizationRepository; import com.habitrpg.android.habitica.data.TagRepository; import com.habitrpg.android.habitica.data.TaskRepository; +import com.habitrpg.android.habitica.data.implementation.ChallengeRepositoryImpl; import com.habitrpg.android.habitica.data.implementation.SetupCustomizationRepositoryImpl; import com.habitrpg.android.habitica.data.implementation.TagRepositoryImpl; import com.habitrpg.android.habitica.data.implementation.TaskRepositoryImpl; @@ -32,6 +34,7 @@ public class RepositoryModule { } @Provides + @Singleton ChallengeLocalRepository provideChallengeLocalRepository(){ return new DbFlowChallengeLocalRepository(); } @@ -47,6 +50,13 @@ public class RepositoryModule { return new TaskRepositoryImpl(localRepository, apiClient); } + @Provides + @Singleton + ChallengeRepository providesChallengeRepository(ChallengeLocalRepository localRepository, ApiClient apiClient) { + return new ChallengeRepositoryImpl(localRepository, apiClient); + } + + @Provides TagLocalRepository providesTagLocalRepository() { return new TagLocalRepositoryImpl(); diff --git a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiClient.java b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiClient.java index 3ee885371..5e0ce48a5 100644 --- a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiClient.java +++ b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiClient.java @@ -11,6 +11,7 @@ import com.magicmicky.habitrpgwrapper.lib.models.Group; import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser; import com.magicmicky.habitrpgwrapper.lib.models.Items; import com.magicmicky.habitrpgwrapper.lib.models.LeaveChallengeBody; +import com.magicmicky.habitrpgwrapper.lib.models.PostChallenge; import com.magicmicky.habitrpgwrapper.lib.models.PostChatMessageResult; import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationRequest; import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationResult; @@ -200,6 +201,10 @@ public interface ApiClient { Observable leaveChallenge(String challengeId, LeaveChallengeBody body); + Observable createChallenge(PostChallenge challenge); + Observable updateChallenge(PostChallenge challenge); + Observable deleteChallenge(String challengeId); + //DEBUG: These calls only work on a local development server Observable debugAddTenGems(); diff --git a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java index b7fc47b8a..f738e5714 100644 --- a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java +++ b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java @@ -8,6 +8,7 @@ import com.magicmicky.habitrpgwrapper.lib.models.Group; import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser; import com.magicmicky.habitrpgwrapper.lib.models.Items; import com.magicmicky.habitrpgwrapper.lib.models.LeaveChallengeBody; +import com.magicmicky.habitrpgwrapper.lib.models.PostChallenge; import com.magicmicky.habitrpgwrapper.lib.models.PostChatMessageResult; import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationRequest; import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationResult; @@ -287,6 +288,16 @@ public interface ApiService { @POST("challenges/{challengeId}/leave") Observable> leaveChallenge(@Path("challengeId") String challengeId, @Body LeaveChallengeBody body); + @POST("challenges") + Observable> createChallenge(@Body PostChallenge challenge); + + @PUT("challenges/{challengeId}") + Observable> updateChallenge(@Path("challengeId") String challengeId, @Body PostChallenge challenge); + + @DELETE("challenges/{challengeId}") + Observable> deleteChallenge(@Path("challengeId") String challengeId); + + //DEBUG: These calls only work on a local development server @POST("debug/add-ten-gems") diff --git a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/PostChallenge.java b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/PostChallenge.java new file mode 100644 index 000000000..25accfd46 --- /dev/null +++ b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/PostChallenge.java @@ -0,0 +1,25 @@ +package com.magicmicky.habitrpgwrapper.lib.models; + +import com.magicmicky.habitrpgwrapper.lib.models.tasks.TasksOrder; + +/** + * Needs to be a separate Class, the normal Challenge has the group as Object + * The Challenge for adding/updating just has the group as id + */ +public class PostChallenge { + public String id; + + public String name; + + public String shortName; + + public String description; + + public String leaderName; + + public String group; + + public int prize; + + public TasksOrder tasksOrder; +} From 8ccc3234176795096d16395baadeb47bd627abdc Mon Sep 17 00:00:00 2001 From: Negue Date: Thu, 20 Apr 2017 22:10:52 +0200 Subject: [PATCH 15/29] Create Challenge with Tasks --- .../res/layout/activity_create_challenge.xml | 5 +- .../android/habitica/ApiClientImpl.java | 11 ++- .../habitica/data/ChallengeRepository.java | 7 +- .../ChallengeRepositoryImpl.java | 47 +++++++++- .../habitica/events/TaskSaveEvent.java | 2 +- .../events/commands/DeleteTaskCommand.java | 6 ++ .../activities/CreateChallengeActivity.java | 94 +++++++++++++++++-- .../habitica/ui/activities/MainActivity.java | 7 ++ .../ui/activities/TaskFormActivity.java | 8 +- .../ChallengeTasksRecyclerViewAdapter.java | 39 +++++++- .../tasks/BaseTasksRecyclerViewAdapter.java | 14 +-- .../habitrpgwrapper/lib/api/ApiClient.java | 1 + .../habitrpgwrapper/lib/api/ApiService.java | 3 + .../lib/models/PostChallenge.java | 2 - .../lib/utils/ChallengeDeserializer.java | 10 +- 15 files changed, 218 insertions(+), 38 deletions(-) diff --git a/Habitica/res/layout/activity_create_challenge.xml b/Habitica/res/layout/activity_create_challenge.xml index aeae2a567..ad1f747ea 100644 --- a/Habitica/res/layout/activity_create_challenge.xml +++ b/Habitica/res/layout/activity_create_challenge.xml @@ -36,7 +36,7 @@ android:layout_height="wrap_content" android:layout_gravity="fill_horizontal" android:hint="New challenge title" - + android:id="@+id/create_challenge_title" android:textColor="@color/white" android:textColorHighlight="@color/brand_500" android:textColorHint="@color/brand_500" @@ -57,6 +57,7 @@ android:hint="Description" android:inputType="textMultiLine" + android:id="@+id/create_challenge_description" android:maxLines="5" android:minLines="3" android:textColor="@color/white" @@ -115,6 +116,7 @@ android:inputType="number" android:textColor="#8a000000" android:text="1" + android:id="@+id/create_challenge_prize" android:textAlignment="center" />