mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-05-19 12:18:59 +00:00
Fix task filtering
This commit is contained in:
parent
5c70b044a9
commit
b8f73373b2
15 changed files with 311 additions and 427 deletions
|
|
@ -2,8 +2,8 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.habitrpg.android.habitica"
|
||||
android:versionCode="1977"
|
||||
android:versionName="1.4.4"
|
||||
android:versionCode="1978"
|
||||
android:versionName="1.5"
|
||||
android:screenOrientation="portrait"
|
||||
android:installLocation="auto" >
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.habitrpg.android.habitica.data.implementation
|
||||
|
||||
import com.github.underscore.U
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository
|
||||
|
|
@ -53,12 +52,12 @@ class ChallengeRepositoryImpl(localRepository: ChallengeLocalRepository, apiClie
|
|||
}
|
||||
|
||||
private fun getTaskOrders(taskList: List<Task>): TasksOrder {
|
||||
val stringListMap = U.groupBy(taskList) { t -> t.type }
|
||||
val stringListMap = taskList.groupBy { t -> t.type }
|
||||
|
||||
val tasksOrder = TasksOrder()
|
||||
|
||||
for ((key, value) in stringListMap) {
|
||||
val taskIdList = U.map<String, Task>(value) { t -> t.id }
|
||||
val taskIdList = value.map { t -> t.id }
|
||||
|
||||
when (key) {
|
||||
Task.TYPE_HABIT -> tasksOrder.habits = taskIdList
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class SoundFile(val theme: String, private val fileName: String) : MediaPlayer.O
|
|||
}
|
||||
|
||||
fun play() {
|
||||
if (isPlaying) {
|
||||
if (isPlaying || file?.path == null) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,149 +0,0 @@
|
|||
package com.habitrpg.android.habitica.helpers;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.realm.OrderedRealmCollection;
|
||||
import io.realm.RealmQuery;
|
||||
|
||||
public class TaskFilterHelper {
|
||||
private List<String> tagsId;
|
||||
private Map<String, String> activeFilters = new HashMap<>();
|
||||
|
||||
public TaskFilterHelper() {
|
||||
tagsId = new ArrayList<>();
|
||||
|
||||
}
|
||||
|
||||
public void addTags(String tags) {
|
||||
this.tagsId.add(tags);
|
||||
}
|
||||
|
||||
public int howMany(@Nullable String type) {
|
||||
return this.tagsId.size() + (isTaskFilterActive(type) ? 1 : 0);
|
||||
}
|
||||
|
||||
private boolean isTaskFilterActive(@Nullable String type) {
|
||||
if (activeFilters.get(type) == null) {
|
||||
return false;
|
||||
}
|
||||
if (Task.TYPE_TODO.equals(type)) {
|
||||
return !Task.FILTER_ACTIVE.equals(activeFilters.get(type));
|
||||
} else {
|
||||
return !Task.FILTER_ALL.equals(activeFilters.get(type));
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getTags() {
|
||||
return this.tagsId;
|
||||
}
|
||||
|
||||
public void setTags(List<String> tagsId) {
|
||||
this.tagsId = tagsId;
|
||||
}
|
||||
|
||||
public boolean isTagChecked(String tagID) {
|
||||
return this.tagsId.contains(tagID);
|
||||
}
|
||||
|
||||
public List<Task> filter(List<Task> tasks) {
|
||||
if (tasks.size() == 0) {
|
||||
return tasks;
|
||||
}
|
||||
List<Task> filtered = new ArrayList<>();
|
||||
String activeFilter = null;
|
||||
if (activeFilters != null && activeFilters.size() > 0) {
|
||||
activeFilter = activeFilters.get(tasks.get(0).getType());
|
||||
}
|
||||
for (Task task : tasks) {
|
||||
if (isFiltered(task, activeFilter)) {
|
||||
filtered.add(task);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
private boolean isFiltered(Task task, @Nullable String activeFilter) {
|
||||
if (!task.containsAllTagIds(tagsId)) {
|
||||
return false;
|
||||
}
|
||||
if (activeFilter != null && !activeFilter.equals(Task.FILTER_ALL)) {
|
||||
switch (activeFilter) {
|
||||
case Task.FILTER_ACTIVE:
|
||||
if (task.getType().equals(Task.TYPE_DAILY)) {
|
||||
return task.isDisplayedActive();
|
||||
} else {
|
||||
return !task.getCompleted();
|
||||
}
|
||||
case Task.FILTER_GRAY:
|
||||
return task.getCompleted() || !task.isDisplayedActive();
|
||||
case Task.FILTER_WEAK:
|
||||
return task.getValue() < 0;
|
||||
case Task.FILTER_STRONG:
|
||||
return task.getValue() >= 0;
|
||||
case Task.FILTER_DATED:
|
||||
return task.getDueDate() != null;
|
||||
case Task.FILTER_COMPLETED:
|
||||
return task.getCompleted();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setActiveFilter(String type, String activeFilter) {
|
||||
activeFilters.put(type, activeFilter);
|
||||
}
|
||||
|
||||
public String getActiveFilter(String type) {
|
||||
return activeFilters.get(type);
|
||||
}
|
||||
|
||||
public RealmQuery<Task> createQuery(OrderedRealmCollection<Task> unfilteredData) {
|
||||
RealmQuery<Task> query = unfilteredData.where();
|
||||
|
||||
if (unfilteredData.size() == 0) {
|
||||
return query;
|
||||
}
|
||||
|
||||
String taskType = unfilteredData.get(0).getType();
|
||||
String activeFilter = getActiveFilter(taskType);
|
||||
|
||||
if (tagsId != null && tagsId.size() > 0) {
|
||||
query = query.in("tags.id", tagsId.toArray(new String[0]));
|
||||
}
|
||||
if (activeFilter != null && !activeFilter.equals(Task.FILTER_ALL)) {
|
||||
switch (activeFilter) {
|
||||
case Task.FILTER_ACTIVE:
|
||||
if (Task.TYPE_DAILY.equals(taskType)) {
|
||||
query = query.equalTo("completed", false).equalTo("isDue", true);
|
||||
} else {
|
||||
query = query.equalTo("completed", false);
|
||||
}
|
||||
break;
|
||||
case Task.FILTER_GRAY:
|
||||
query = query.equalTo("completed", true).or().equalTo("isDue", false);
|
||||
break;
|
||||
case Task.FILTER_WEAK:
|
||||
query = query.lessThan("value", 0.0d);
|
||||
break;
|
||||
case Task.FILTER_STRONG:
|
||||
query = query.greaterThanOrEqualTo("value", 0.0d);
|
||||
break;
|
||||
case Task.FILTER_DATED:
|
||||
query = query.isNotNull("dueDate");
|
||||
break;
|
||||
case Task.FILTER_COMPLETED:
|
||||
query = query.equalTo("completed", true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
package com.habitrpg.android.habitica.helpers
|
||||
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
|
||||
import io.realm.OrderedRealmCollection
|
||||
import io.realm.RealmQuery
|
||||
|
||||
class TaskFilterHelper {
|
||||
private var tagsId: MutableList<String> = ArrayList()
|
||||
private val activeFilters = HashMap<String, String>()
|
||||
|
||||
var tags: MutableList<String>
|
||||
get() = this.tagsId
|
||||
set(tagsId) {
|
||||
this.tagsId = tagsId
|
||||
}
|
||||
|
||||
fun howMany(type: String?): Int {
|
||||
return this.tagsId.size + if (isTaskFilterActive(type)) 1 else 0
|
||||
}
|
||||
|
||||
private fun isTaskFilterActive(type: String?): Boolean {
|
||||
if (activeFilters[type] == null) {
|
||||
return false
|
||||
}
|
||||
return if (Task.TYPE_TODO == type) {
|
||||
Task.FILTER_ACTIVE != activeFilters[type]
|
||||
} else {
|
||||
Task.FILTER_ALL != activeFilters[type]
|
||||
}
|
||||
}
|
||||
|
||||
fun isTagChecked(tagID: String): Boolean {
|
||||
return this.tagsId.contains(tagID)
|
||||
}
|
||||
|
||||
fun filter(tasks: List<Task>): List<Task> {
|
||||
if (tasks.isEmpty()) {
|
||||
return tasks
|
||||
}
|
||||
val filtered = ArrayList<Task>()
|
||||
var activeFilter: String? = null
|
||||
if (activeFilters.size > 0) {
|
||||
activeFilter = activeFilters[tasks[0].type]
|
||||
}
|
||||
for (task in tasks) {
|
||||
if (isFiltered(task, activeFilter)) {
|
||||
filtered.add(task)
|
||||
}
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
private fun isFiltered(task: Task, activeFilter: String?): Boolean {
|
||||
if (!task.containsAllTagIds(tagsId)) {
|
||||
return false
|
||||
}
|
||||
if (activeFilter != null && activeFilter != Task.FILTER_ALL) {
|
||||
when (activeFilter) {
|
||||
Task.FILTER_ACTIVE -> return if (task.type == Task.TYPE_DAILY) {
|
||||
task.isDisplayedActive
|
||||
} else {
|
||||
!task.completed
|
||||
}
|
||||
Task.FILTER_GRAY -> return task.completed || !task.isDisplayedActive
|
||||
Task.FILTER_WEAK -> return task.value < 0
|
||||
Task.FILTER_STRONG -> return task.value >= 0
|
||||
Task.FILTER_DATED -> return task.dueDate != null
|
||||
Task.FILTER_COMPLETED -> return task.completed
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun setActiveFilter(type: String, activeFilter: String) {
|
||||
activeFilters[type] = activeFilter
|
||||
}
|
||||
|
||||
fun getActiveFilter(type: String): String? {
|
||||
return activeFilters[type]
|
||||
}
|
||||
|
||||
fun createQuery(unfilteredData: OrderedRealmCollection<Task>): RealmQuery<Task> {
|
||||
var query = unfilteredData.where()
|
||||
|
||||
if (unfilteredData.size == 0) {
|
||||
return query
|
||||
}
|
||||
|
||||
val taskType = unfilteredData[0].type
|
||||
val activeFilter = getActiveFilter(taskType)
|
||||
|
||||
if (tagsId.size > 0) {
|
||||
query = query.`in`("tags.id", tagsId.toTypedArray())
|
||||
}
|
||||
if (activeFilter != null && activeFilter != Task.FILTER_ALL) {
|
||||
when (activeFilter) {
|
||||
Task.FILTER_ACTIVE -> query = if (Task.TYPE_DAILY == taskType) {
|
||||
query.equalTo("completed", false).equalTo("isDue", true)
|
||||
} else {
|
||||
query.equalTo("completed", false)
|
||||
}
|
||||
Task.FILTER_GRAY -> query = query.equalTo("completed", true).or().equalTo("isDue", false)
|
||||
Task.FILTER_WEAK -> query = query.lessThan("value", 0.0)
|
||||
Task.FILTER_STRONG -> query = query.greaterThanOrEqualTo("value", 0.0)
|
||||
Task.FILTER_DATED -> query = query.isNotNull("dueDate")
|
||||
Task.FILTER_COMPLETED -> query = query.equalTo("completed", true)
|
||||
}
|
||||
}
|
||||
return query
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ import android.support.v7.widget.LinearLayoutManager
|
|||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.*
|
||||
import android.widget.*
|
||||
import com.github.underscore.U
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
|
|
@ -181,7 +180,7 @@ class CreateChallengeActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
val builder = AlertDialog.Builder(this)
|
||||
.setMessage(U.join(errorMessages, "\n"))
|
||||
.setMessage(errorMessages.joinToString("\n"))
|
||||
|
||||
val alert = builder.create()
|
||||
alert.show()
|
||||
|
|
|
|||
|
|
@ -1,197 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.adapter.social.challenges;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.github.underscore.U;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.helpers.TaskFilterHelper;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
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 java.util.List;
|
||||
|
||||
import io.reactivex.BackpressureStrategy;
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.subjects.PublishSubject;
|
||||
|
||||
public class ChallengeTasksRecyclerViewAdapter
|
||||
extends SortableTasksRecyclerViewAdapter<BaseTaskViewHolder> {
|
||||
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 PublishSubject<Task> addItemSubject = PublishSubject.create();
|
||||
private boolean openTaskDisabled;
|
||||
private boolean taskActionsDisabled;
|
||||
|
||||
public ChallengeTasksRecyclerViewAdapter(@Nullable TaskFilterHelper taskFilterHelper, int layoutResource,
|
||||
Context newContext, String userID, @Nullable SortTasksCallback sortCallback,
|
||||
boolean openTaskDisabled, boolean taskActionsDisabled) {
|
||||
super("", taskFilterHelper, 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.getFilteredContent().get(position);
|
||||
|
||||
if (task.getType().equals(Task.TYPE_HABIT))
|
||||
return TYPE_HABIT;
|
||||
|
||||
if (task.getType().equals(Task.TYPE_DAILY))
|
||||
return TYPE_DAILY;
|
||||
|
||||
if (task.getType().equals(Task.TYPE_TODO))
|
||||
return TYPE_TODO;
|
||||
|
||||
if (task.getType().equals(Task.TYPE_REWARD))
|
||||
return TYPE_REWARD;
|
||||
|
||||
if (addItemSubject.hasObservers() && task.getType().equals(TASK_TYPE_ADD_ITEM))
|
||||
return TYPE_ADD_ITEM;
|
||||
|
||||
return TYPE_HEADER;
|
||||
}
|
||||
|
||||
public Flowable<Task> addItemObservable(){
|
||||
return addItemSubject.toFlowable(BackpressureStrategy.BUFFER);
|
||||
}
|
||||
|
||||
public int addTaskUnder(Task taskToAdd, @Nullable Task taskAbove) {
|
||||
int position = U.findIndex(this.getContent(), t -> t.getId().equals(taskAbove.getId()));
|
||||
|
||||
getContent().add(position + 1, taskToAdd);
|
||||
filter();
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
@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));
|
||||
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), addItemSubject);
|
||||
break;
|
||||
default:
|
||||
viewHolder = new DividerViewHolder(getContentView(parent, R.layout.challenge_task_divider));
|
||||
break;
|
||||
}
|
||||
|
||||
viewHolder.setDisabled(openTaskDisabled, taskActionsDisabled);
|
||||
return viewHolder;
|
||||
}
|
||||
|
||||
public List<Task> getTaskList(){
|
||||
return U.map(getContent(), t -> t);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param task
|
||||
* @return true if task found&updated
|
||||
*/
|
||||
public boolean replaceTask(Task task) {
|
||||
int i;
|
||||
for (i = 0; i < this.getContent().size(); ++i) {
|
||||
if (getContent().get(i).getId().equals(task.getId())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < getContent().size()) {
|
||||
getContent().set(i, task);
|
||||
|
||||
filter();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public class AddItemViewHolder extends BaseTaskViewHolder {
|
||||
|
||||
private Button addBtn;
|
||||
private PublishSubject<Task> callback;
|
||||
private Task newTask;
|
||||
|
||||
AddItemViewHolder(View itemView, PublishSubject<Task> callback) {
|
||||
super(itemView);
|
||||
this.callback = callback;
|
||||
|
||||
addBtn = itemView.findViewById(R.id.btn_add_task);
|
||||
addBtn.setClickable(true);
|
||||
addBtn.setOnClickListener(view -> callback.onNext(newTask));
|
||||
setContext(itemView.getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindHolder(@NonNull Task newTask, int position) {
|
||||
this.newTask = newTask;
|
||||
addBtn.setText(newTask.getText());
|
||||
}
|
||||
}
|
||||
|
||||
private class DividerViewHolder extends BaseTaskViewHolder {
|
||||
|
||||
private TextView divider_name;
|
||||
|
||||
DividerViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
|
||||
divider_name = itemView.findViewById(R.id.divider_name);
|
||||
|
||||
setContext(itemView.getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindHolder(@NonNull Task newTask, int position) {
|
||||
divider_name.setText(newTask.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
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.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.TaskFilterHelper
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.ui.adapter.tasks.SortableTasksRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.viewHolders.tasks.*
|
||||
import io.reactivex.BackpressureStrategy
|
||||
import io.reactivex.Flowable
|
||||
import io.reactivex.subjects.PublishSubject
|
||||
|
||||
class ChallengeTasksRecyclerViewAdapter(taskFilterHelper: TaskFilterHelper?, layoutResource: Int,
|
||||
newContext: Context, userID: String, sortCallback: SortableTasksRecyclerViewAdapter.SortTasksCallback?,
|
||||
private val openTaskDisabled: Boolean, private val taskActionsDisabled: Boolean) : SortableTasksRecyclerViewAdapter<BaseTaskViewHolder>("", taskFilterHelper, layoutResource, newContext, userID, sortCallback) {
|
||||
|
||||
private val addItemSubject = PublishSubject.create<Task>()
|
||||
|
||||
val taskList: MutableList<Task>
|
||||
get() = content?.map { t -> t }?.toMutableList() ?: mutableListOf()
|
||||
|
||||
override fun injectThis(component: AppComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
override fun loadFromDatabase(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val task = this.filteredContent?.get(position)
|
||||
|
||||
if (task?.type == Task.TYPE_HABIT) {
|
||||
return TYPE_HABIT
|
||||
}
|
||||
if (task?.type == Task.TYPE_DAILY) {
|
||||
return TYPE_DAILY
|
||||
}
|
||||
if (task?.type == Task.TYPE_TODO) {
|
||||
return TYPE_TODO
|
||||
}
|
||||
if (task?.type == Task.TYPE_REWARD) {
|
||||
return TYPE_REWARD
|
||||
}
|
||||
|
||||
return if (addItemSubject.hasObservers() && task?.type == TASK_TYPE_ADD_ITEM) TYPE_ADD_ITEM else TYPE_HEADER
|
||||
|
||||
}
|
||||
|
||||
fun addItemObservable(): Flowable<Task> {
|
||||
return addItemSubject.toFlowable(BackpressureStrategy.BUFFER)
|
||||
}
|
||||
|
||||
fun addTaskUnder(taskToAdd: Task, taskAbove: Task?): Int {
|
||||
val position = content?.indexOfFirst { t -> t.id == taskAbove?.id } ?: 0
|
||||
|
||||
content?.add(position + 1, taskToAdd)
|
||||
filter()
|
||||
|
||||
return position
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseTaskViewHolder {
|
||||
val viewHolder: BaseTaskViewHolder = when (viewType) {
|
||||
TYPE_HABIT -> HabitViewHolder(getContentView(parent, R.layout.habit_item_card))
|
||||
TYPE_DAILY -> DailyViewHolder(getContentView(parent, R.layout.daily_item_card))
|
||||
TYPE_TODO -> TodoViewHolder(getContentView(parent, R.layout.todo_item_card))
|
||||
TYPE_REWARD -> RewardViewHolder(getContentView(parent, R.layout.reward_item_card))
|
||||
TYPE_ADD_ITEM -> AddItemViewHolder(getContentView(parent, R.layout.challenge_add_task_item), addItemSubject)
|
||||
else -> DividerViewHolder(getContentView(parent, R.layout.challenge_task_divider))
|
||||
}
|
||||
|
||||
viewHolder.setDisabled(openTaskDisabled, taskActionsDisabled)
|
||||
return viewHolder
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param task
|
||||
* @return true if task found&updated
|
||||
*/
|
||||
fun replaceTask(task: Task): Boolean {
|
||||
var i = 0
|
||||
while (i < this.content?.size ?: 0) {
|
||||
if (content?.get(i)?.id == task.id) {
|
||||
break
|
||||
}
|
||||
++i
|
||||
}
|
||||
if (i < content?.size ?: 0) {
|
||||
content?.set(i, task)
|
||||
|
||||
filter()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
inner class AddItemViewHolder internal constructor(itemView: View, private val callback: PublishSubject<Task>) : BaseTaskViewHolder(itemView) {
|
||||
|
||||
private val addBtn: Button = itemView.findViewById(R.id.btn_add_task)
|
||||
private var newTask: Task? = null
|
||||
|
||||
init {
|
||||
addBtn.isClickable = true
|
||||
addBtn.setOnClickListener { newTask.notNull { callback.onNext(it) } }
|
||||
}
|
||||
|
||||
override fun bindHolder(newTask: Task, position: Int) {
|
||||
this.newTask = newTask
|
||||
addBtn.text = newTask.text
|
||||
}
|
||||
}
|
||||
|
||||
private inner class DividerViewHolder internal constructor(itemView: View) : BaseTaskViewHolder(itemView) {
|
||||
|
||||
private val dividerName: TextView = itemView.findViewById(R.id.divider_name)
|
||||
|
||||
override fun bindHolder(newTask: Task, position: Int) {
|
||||
dividerName.text = newTask.text
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TASK_TYPE_ADD_ITEM = "ADD_ITEM"
|
||||
|
||||
private const val TYPE_HEADER = 0
|
||||
private const val TYPE_HABIT = 1
|
||||
private const val TYPE_DAILY = 2
|
||||
private const val TYPE_TODO = 3
|
||||
private const val TYPE_REWARD = 4
|
||||
private const val TYPE_ADD_ITEM = 5
|
||||
}
|
||||
}
|
||||
|
|
@ -67,10 +67,10 @@ abstract class BaseTasksRecyclerViewAdapter<VH : BaseTaskViewHolder>(var taskTyp
|
|||
protected fun getContentView(parent: ViewGroup, layoutResource: Int): View =
|
||||
LayoutInflater.from(parent.context).inflate(layoutResource, parent, false)
|
||||
|
||||
fun updateTask(task: Task) {
|
||||
private fun updateTask(task: Task) {
|
||||
if (taskType != task.type)
|
||||
return
|
||||
var i: Int = 0
|
||||
var i = 0
|
||||
while (i < this.content!!.size) {
|
||||
if (content!![i].id == task.id) {
|
||||
break
|
||||
|
|
@ -88,13 +88,15 @@ abstract class BaseTasksRecyclerViewAdapter<VH : BaseTaskViewHolder>(var taskTyp
|
|||
filteredContent = content
|
||||
} else {
|
||||
filteredContent = ArrayList()
|
||||
filteredContent!!.addAll(this.taskFilterHelper.filter(content))
|
||||
content.notNull {
|
||||
filteredContent?.addAll(this.taskFilterHelper.filter(it))
|
||||
}
|
||||
}
|
||||
|
||||
this.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun loadContent(forced: Boolean) {
|
||||
private fun loadContent(forced: Boolean) {
|
||||
if (this.content == null || forced) {
|
||||
taskRepository.getTasks(this.taskType, this.userID!!)
|
||||
.flatMap<Task> { Flowable.fromIterable(it) }
|
||||
|
|
@ -116,37 +118,4 @@ abstract class BaseTasksRecyclerViewAdapter<VH : BaseTaskViewHolder>(var taskTyp
|
|||
}
|
||||
|
||||
open fun loadFromDatabase(): Boolean = true
|
||||
|
||||
fun checkTask(task: Task, completed: Boolean?) {
|
||||
if (taskType != task.type)
|
||||
return
|
||||
|
||||
if (completed!! && task.type == "todo") {
|
||||
// remove from the list
|
||||
content!!.remove(task)
|
||||
}
|
||||
this.updateTask(task)
|
||||
filter()
|
||||
}
|
||||
|
||||
fun addTask(task: Task) {
|
||||
if (taskType != task.type)
|
||||
return
|
||||
|
||||
content!!.add(0, task)
|
||||
filter()
|
||||
}
|
||||
|
||||
fun removeTask(deletedTaskId: String) {
|
||||
val taskToDelete: Task? = content?.firstOrNull { it.id == deletedTaskId }
|
||||
|
||||
if (taskToDelete != null) {
|
||||
content?.remove(taskToDelete)
|
||||
filter()
|
||||
}
|
||||
}
|
||||
|
||||
open fun setDailyResetOffset(dayStart: Int) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,9 +141,7 @@ abstract class RealmBaseTasksRecyclerViewAdapter<VH : BaseTaskViewHolder>(privat
|
|||
LayoutInflater.from(parent.context).inflate(layoutResource, parent, false)
|
||||
|
||||
final override fun filter() {
|
||||
if (unfilteredData == null) {
|
||||
return
|
||||
}
|
||||
val unfilteredData = this.unfilteredData ?: return
|
||||
|
||||
if (taskFilterHelper != null) {
|
||||
val query = taskFilterHelper.createQuery(unfilteredData)
|
||||
|
|
|
|||
|
|
@ -260,9 +260,7 @@ open class TaskRecyclerViewFragment : BaseFragment(), View.OnClickListener, Swip
|
|||
}
|
||||
|
||||
fun setActiveFilter(activeFilter: String) {
|
||||
if (classType != null) {
|
||||
taskFilterHelper.setActiveFilter(classType, activeFilter)
|
||||
}
|
||||
taskFilterHelper.setActiveFilter(classType ?: "", activeFilter)
|
||||
recyclerAdapter?.filter()
|
||||
|
||||
if (activeFilter == Task.FILTER_COMPLETED) {
|
||||
|
|
@ -271,7 +269,7 @@ open class TaskRecyclerViewFragment : BaseFragment(), View.OnClickListener, Swip
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val CLASS_TYPE_KEY = "CLASS_TYPE_KEY"
|
||||
private const val CLASS_TYPE_KEY = "CLASS_TYPE_KEY"
|
||||
|
||||
fun newInstance(context: Context?, user: User?, classType: String): TaskRecyclerViewFragment {
|
||||
val fragment = TaskRecyclerViewFragment()
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ class TasksFragment : BaseMainFragment() {
|
|||
@Inject
|
||||
lateinit var tagRepository: TagRepository
|
||||
|
||||
internal var refreshItem: MenuItem? = null
|
||||
internal var floatingMenu: FloatingActionMenu? = null
|
||||
private var refreshItem: MenuItem? = null
|
||||
private var floatingMenu: FloatingActionMenu? = null
|
||||
internal var viewFragmentsDictionary: MutableMap<Int, TaskRecyclerViewFragment>? = WeakHashMap()
|
||||
|
||||
private var displayingTaskForm: Boolean = false
|
||||
|
|
@ -71,7 +71,7 @@ class TasksFragment : BaseMainFragment() {
|
|||
todoFab?.setOnClickListener { openNewTaskActivity(Task.TYPE_TODO) }
|
||||
val rewardFab = floatingMenu?.findViewById<FloatingActionButton>(R.id.fab_new_reward)
|
||||
rewardFab?.setOnClickListener { openNewTaskActivity(Task.TYPE_REWARD) }
|
||||
floatingMenu?.setOnMenuButtonLongClickListener { this.onFloatingMenuLongClicked(it) }
|
||||
floatingMenu?.setOnMenuButtonLongClickListener { this.onFloatingMenuLongClicked() }
|
||||
|
||||
loadTaskLists()
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ class TasksFragment : BaseMainFragment() {
|
|||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun onFloatingMenuLongClicked(view: View): Boolean {
|
||||
private fun onFloatingMenuLongClicked(): Boolean {
|
||||
val currentFragment = activeFragment
|
||||
if (currentFragment != null) {
|
||||
val className = currentFragment.className
|
||||
|
|
@ -148,7 +148,7 @@ class TasksFragment : BaseMainFragment() {
|
|||
}
|
||||
dialog.setListener(object : TaskFilterDialog.OnFilterCompletedListener {
|
||||
|
||||
override fun onFilterCompleted(activeTaskFilter: String?, activeTags: List<String>?) {
|
||||
override fun onFilterCompleted(activeTaskFilter: String?, activeTags: MutableList<String>) {
|
||||
if (viewFragmentsDictionary == null) {
|
||||
return
|
||||
}
|
||||
|
|
@ -329,10 +329,6 @@ class TasksFragment : BaseMainFragment() {
|
|||
|
||||
//endregion Events
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
|
|
@ -383,7 +379,7 @@ class TasksFragment : BaseMainFragment() {
|
|||
override fun addToBackStack(): Boolean = false
|
||||
|
||||
companion object {
|
||||
private val TASK_CREATED_RESULT = 1
|
||||
private val TASK_UPDATED_RESULT = 2
|
||||
private const val TASK_CREATED_RESULT = 1
|
||||
private const val TASK_UPDATED_RESULT = 2
|
||||
}
|
||||
}
|
||||
|
|
@ -14,14 +14,17 @@ import com.habitrpg.android.habitica.extensions.layoutInflater
|
|||
open class HabiticaAlertDialog(context: Context) : AlertDialog(context) {
|
||||
|
||||
private val view: LinearLayout = LayoutInflater.from(context).inflate(R.layout.dialog_habitica_base, null) as LinearLayout
|
||||
private val titleTextView: TextView by bindView(R.id.titleTextView)
|
||||
private val subtitleTextView: TextView by bindView(R.id.subtitleTextView)
|
||||
private val messageTextView: TextView by bindView(R.id.messageTextView)
|
||||
private var titleTextView: TextView
|
||||
private var subtitleTextView: TextView
|
||||
private var messageTextView: TextView
|
||||
|
||||
private var additionalContentView: View? = null
|
||||
|
||||
init {
|
||||
setView(view)
|
||||
titleTextView = view.findViewById(R.id.titleTextView)
|
||||
subtitleTextView = view.findViewById(R.id.subtitleTextView)
|
||||
messageTextView = view.findViewById(R.id.messageTextView)
|
||||
}
|
||||
|
||||
override fun setTitle(title: CharSequence?) {
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ import com.habitrpg.android.habitica.ui.helpers.bindView
|
|||
|
||||
abstract class InsufficientCurrencyDialog(context: Context) : AlertDialog(context) {
|
||||
|
||||
protected val imageView: ImageView by bindView(R.id.imageView)
|
||||
protected val textView: TextView by bindView(R.id.textView)
|
||||
protected var imageView: ImageView
|
||||
protected var textView: TextView
|
||||
|
||||
init {
|
||||
|
||||
|
|
@ -23,6 +23,9 @@ abstract class InsufficientCurrencyDialog(context: Context) : AlertDialog(contex
|
|||
val view = inflater.inflate(R.layout.dialog_insufficient_currency, null)
|
||||
setView(view)
|
||||
|
||||
imageView = view.findViewById(R.id.imageView)
|
||||
textView = view.findViewById(R.id.textView)
|
||||
|
||||
this.setButton(AlertDialog.BUTTON_NEUTRAL, context.getString(R.string.close)) { _, _ -> this.dismiss() }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import com.habitrpg.android.habitica.data.TagRepository
|
|||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.Tag
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.ui.helpers.bindView
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.functions.Consumer
|
||||
import java.util.*
|
||||
|
|
@ -34,13 +33,14 @@ class TaskFilterDialog(context: Context, component: AppComponent?) : AlertDialog
|
|||
@Inject
|
||||
lateinit var repository: TagRepository
|
||||
|
||||
private val taskTypeTitle: TextView by bindView(R.id.task_type_title)
|
||||
private val taskFilters: RadioGroup by bindView(R.id.task_filter_wrapper)
|
||||
private val allTaskFilter: RadioButton by bindView(R.id.all_task_filter)
|
||||
private val secondTaskFilter: RadioButton by bindView(R.id.second_task_filter)
|
||||
private val thirdTaskFilter: RadioButton by bindView(R.id.third_task_filter)
|
||||
private val tagsEditButton: Button by bindView(R.id.tag_edit_button)
|
||||
private val tagsList: LinearLayout by bindView(R.id.tags_list)
|
||||
private var taskTypeTitle: TextView
|
||||
private var taskFilters: RadioGroup
|
||||
private var allTaskFilter: RadioButton
|
||||
private var secondTaskFilter: RadioButton
|
||||
private var thirdTaskFilter: RadioButton
|
||||
private var tagsEditButton: Button
|
||||
private var tagsList: LinearLayout
|
||||
|
||||
private var taskType: String? = null
|
||||
private var listener: OnFilterCompletedListener? = null
|
||||
|
||||
|
|
@ -60,11 +60,19 @@ class TaskFilterDialog(context: Context, component: AppComponent?) : AlertDialog
|
|||
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val view = inflater.inflate(R.layout.dialog_task_filter, null)
|
||||
setTitle(R.string.filters)
|
||||
setView(view)
|
||||
|
||||
taskTypeTitle = view.findViewById(R.id.task_type_title)
|
||||
taskFilters = view.findViewById(R.id.task_filter_wrapper)
|
||||
allTaskFilter = view.findViewById(R.id.all_task_filter)
|
||||
secondTaskFilter = view.findViewById(R.id.second_task_filter)
|
||||
thirdTaskFilter = view.findViewById(R.id.third_task_filter)
|
||||
tagsEditButton = view.findViewById(R.id.tag_edit_button)
|
||||
tagsList = view.findViewById(R.id.tags_list)
|
||||
|
||||
taskFilters.setOnCheckedChangeListener(this)
|
||||
|
||||
setTitle(R.string.filters)
|
||||
setView(view)
|
||||
this.setButton(AlertDialog.BUTTON_POSITIVE, context.getString(R.string.done)) { _, _ ->
|
||||
if (isEditing) {
|
||||
stopEditing()
|
||||
|
|
@ -78,7 +86,7 @@ class TaskFilterDialog(context: Context, component: AppComponent?) : AlertDialog
|
|||
tagsEditButton.setOnClickListener { editButtonClicked() }
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle) {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val clearButton = getButton(AlertDialog.BUTTON_NEUTRAL)
|
||||
if (clearButton != null) {
|
||||
|
|
@ -262,7 +270,7 @@ class TaskFilterDialog(context: Context, component: AppComponent?) : AlertDialog
|
|||
return -1
|
||||
}
|
||||
|
||||
fun setTaskType(taskType: String, activeFilter: String) {
|
||||
fun setTaskType(taskType: String, activeFilter: String?) {
|
||||
this.taskType = taskType
|
||||
when (taskType) {
|
||||
Task.TYPE_HABIT -> {
|
||||
|
|
@ -358,6 +366,6 @@ class TaskFilterDialog(context: Context, component: AppComponent?) : AlertDialog
|
|||
|
||||
interface OnFilterCompletedListener {
|
||||
|
||||
fun onFilterCompleted(activeTaskFilter: String?, activeTags: List<String>?)
|
||||
fun onFilterCompleted(activeTaskFilter: String?, activeTags: MutableList<String>)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue