mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-05-25 15:16:01 +00:00
Fix task reordering
This commit is contained in:
parent
41072d1cae
commit
6bdba57b6d
22 changed files with 820 additions and 992 deletions
|
|
@ -1,7 +1,7 @@
|
|||
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
|
||||
android:id="@+id/refresh_layout"
|
||||
android:id="@+id/refreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#fff"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/refresh_layout"
|
||||
android:id="@+id/refreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/refresh_layout"
|
||||
android:id="@+id/refreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/refresh_layout"
|
||||
android:id="@+id/refreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
|
@ -37,13 +37,13 @@
|
|||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/empty_view_title"
|
||||
android:id="@+id/emptyViewTitle"
|
||||
tools:text="No Items"
|
||||
android:textSize="@dimen/card_medium_text"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/empty_view_description"
|
||||
android:id="@+id/emptyViewDescription"
|
||||
tools:text="No Items" />
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ interface TaskRepository : BaseRepository {
|
|||
|
||||
fun swapTaskPosition(firstPosition: Int, secondPosition: Int)
|
||||
|
||||
fun updateTaskPosition(oldPosition: Int, newPosition: Int): Observable<List<String>>
|
||||
fun updateTaskPosition(taskType: String, oldPosition: Int, newPosition: Int): Observable<List<String>>
|
||||
|
||||
fun getUnmanagedTask(taskid: String): Observable<Task>
|
||||
|
||||
|
|
|
|||
|
|
@ -175,8 +175,8 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli
|
|||
localRepository.swapTaskPosition(firstPosition, secondPosition)
|
||||
}
|
||||
|
||||
override fun updateTaskPosition(oldPosition: Int, newPosition: Int): Observable<List<String>> {
|
||||
return localRepository.getTaskAtPosition(oldPosition)
|
||||
override fun updateTaskPosition(taskType: String, oldPosition: Int, newPosition: Int): Observable<List<String>> {
|
||||
return localRepository.getTaskAtPosition(taskType, oldPosition)
|
||||
.first()
|
||||
.flatMap { task ->
|
||||
if (task.isValid) {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ interface TaskLocalRepository : BaseLocalRepository {
|
|||
|
||||
fun swapTaskPosition(firstPosition: Int, secondPosition: Int)
|
||||
|
||||
fun getTaskAtPosition(currentPosition: Int): Observable<Task>
|
||||
fun getTaskAtPosition(taskType: String, position: Int): Observable<Task>
|
||||
|
||||
fun updateIsdue(daily: TaskList): Observable<TaskList>
|
||||
|
||||
|
|
|
|||
|
|
@ -20,14 +20,15 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
.equalTo("type", taskType)
|
||||
.equalTo("userId", userID)
|
||||
.findAllSorted("position")
|
||||
.sort("dateCreated", Sort.DESCENDING)
|
||||
.asObservable()
|
||||
.filter({ it.isLoaded })
|
||||
.retry(1)
|
||||
}
|
||||
|
||||
override fun getTasks(userId: String): Observable<RealmResults<Task>> {
|
||||
return realm.where(Task::class.java).equalTo("userId", userId).findAll().asObservable()
|
||||
return realm.where(Task::class.java).equalTo("userId", userId)
|
||||
.findAllSorted("position")
|
||||
.asObservable()
|
||||
.filter({ it.isLoaded })
|
||||
}
|
||||
|
||||
|
|
@ -146,8 +147,8 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
}
|
||||
}
|
||||
|
||||
override fun getTaskAtPosition(currentPosition: Int): Observable<Task> {
|
||||
return realm.where(Task::class.java).equalTo("position", currentPosition).findFirstAsync().asObservable<RealmObject>()
|
||||
override fun getTaskAtPosition(taskType: String, position: Int): Observable<Task> {
|
||||
return realm.where(Task::class.java).equalTo("type", taskType).equalTo("position", position).findFirstAsync().asObservable<RealmObject>()
|
||||
.filter { realmObject -> realmObject.isLoaded }
|
||||
.cast(Task::class.java)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ open class Equipment : RealmObject() {
|
|||
var value: Double = 0.toDouble()
|
||||
var type: String = ""
|
||||
@PrimaryKey
|
||||
var key: String = ""
|
||||
var key: String? = ""
|
||||
var klass: String = ""
|
||||
var specialClass: String = ""
|
||||
var index: String = ""
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ public interface TaskRecyclerViewAdapter {
|
|||
void filter();
|
||||
|
||||
void notifyItemMoved(int adapterPosition, int adapterPosition1);
|
||||
void notifyDataSetChanged();
|
||||
int getItemViewType(int position);
|
||||
|
||||
void setIgnoreUpdates(boolean ignoreUpdates);
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class EquipmentOverviewFragment : BaseMainFragment() {
|
|||
if (this.nameMapping.isEmpty()) {
|
||||
compositeSubscription.add(inventoryRepository.ownedEquipment.subscribe(Action1 {
|
||||
for (gear in it) {
|
||||
this.nameMapping.put(gear.key, gear.text)
|
||||
this.nameMapping.put(gear.key ?: "", gear.text)
|
||||
}
|
||||
|
||||
setEquipmentNames()
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public class ChatListFragment extends BaseFragment implements SwipeRefreshLayout
|
|||
public boolean isTavern;
|
||||
@BindView(R.id.recyclerView)
|
||||
RecyclerView recyclerView;
|
||||
@BindView(R.id.refresh_layout)
|
||||
@BindView(R.id.refreshLayout)
|
||||
SwipeRefreshLayout swipeRefreshLayout;
|
||||
@BindView(R.id.emojiButton)
|
||||
ImageButton emojiButton;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public class ChallengeListFragment extends BaseMainFragment implements SwipeRefr
|
|||
@Named(AppModule.NAMED_USER_ID)
|
||||
String userId;
|
||||
|
||||
@BindView(R.id.refresh_layout)
|
||||
@BindView(R.id.refreshLayout)
|
||||
SwipeRefreshLayout swipeRefreshLayout;
|
||||
@BindView(R.id.recyclerView)
|
||||
RecyclerViewEmptySupport recyclerView;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public class PartyDetailFragment extends BaseFragment {
|
|||
@Named(AppModule.NAMED_USER_ID)
|
||||
String userId;
|
||||
|
||||
@BindView(R.id.refresh_layout)
|
||||
@BindView(R.id.refreshLayout)
|
||||
SwipeRefreshLayout refreshLayout;
|
||||
|
||||
@BindView(R.id.party_invitation_wrapper)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public class PartyMemberListFragment extends BaseFragment {
|
|||
|
||||
@BindView(R.id.recyclerView)
|
||||
RecyclerView recyclerView;
|
||||
@BindView(R.id.refresh_layout)
|
||||
@BindView(R.id.refreshLayout)
|
||||
SwipeRefreshLayout refreshLayout;
|
||||
private PartyMemberRecyclerViewAdapter adapter;
|
||||
private View view;
|
||||
|
|
|
|||
|
|
@ -1,108 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter;
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class RewardsRecyclerviewFragment extends TaskRecyclerViewFragment {
|
||||
|
||||
public static RewardsRecyclerviewFragment newInstance(Context context, @Nullable User user, String classType) {
|
||||
RewardsRecyclerviewFragment fragment = new RewardsRecyclerviewFragment();
|
||||
fragment.setRetainInstance(true);
|
||||
fragment.user = user;
|
||||
fragment.classType = classType;
|
||||
fragment.tutorialStepIdentifier = "rewards";
|
||||
|
||||
fragment.tutorialTexts = new ArrayList<>(Arrays.asList(context.getString(R.string.tutorial_rewards_1),
|
||||
context.getString(R.string.tutorial_rewards_2)));
|
||||
fragment.tutorialCanBeDeferred = false;
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
if (layoutManager != null) {
|
||||
((GridLayoutManager)layoutManager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
|
||||
@Override
|
||||
public int getSpanSize(int position) {
|
||||
if (recyclerAdapter.getItemViewType(position) < 2) {
|
||||
return ((GridLayoutManager)layoutManager).getSpanCount();
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
inventoryRepository.retrieveInAppRewards().subscribe(shopItems -> {}, RxErrorHandler.handleEmptyError());
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
final View finalView = view;
|
||||
finalView.post(() -> setGridSpanCount(finalView.getWidth()));
|
||||
recyclerView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.white));
|
||||
recyclerView.setItemAnimator(new SafeDefaultItemAnimator());
|
||||
|
||||
inventoryRepository.getInAppRewards().subscribe(shopItems -> {
|
||||
if (recyclerAdapter != null) {
|
||||
((RewardsRecyclerViewAdapter)recyclerAdapter).updateItemRewards(shopItems);
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected LinearLayoutManager getLayoutManager(FragmentActivity context) {
|
||||
return new GridLayoutManager(context, 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
swipeRefreshLayout.setRefreshing(true);
|
||||
userRepository.retrieveUser(true, true)
|
||||
.flatMap(user -> inventoryRepository.retrieveInAppRewards())
|
||||
.doOnTerminate(() -> {
|
||||
if (swipeRefreshLayout != null) {
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
}).subscribe(user1 -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
private void setGridSpanCount(int width) {
|
||||
int spanCount = 0;
|
||||
if (getContext() != null && getContext().getResources() != null) {
|
||||
float itemWidth;
|
||||
itemWidth = getContext().getResources().getDimension(R.dimen.reward_width);
|
||||
|
||||
spanCount = (int) (width / itemWidth);
|
||||
}
|
||||
|
||||
if (spanCount == 0) {
|
||||
spanCount = 1;
|
||||
}
|
||||
((GridLayoutManager)layoutManager).setSpanCount(spanCount);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.tasks
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.widget.GridLayoutManager
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.shops.ShopItem
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import kotlinx.android.synthetic.main.fragment_refresh_recyclerview.*
|
||||
import rx.functions.Action1
|
||||
import java.util.*
|
||||
|
||||
class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() {
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val view = super.onCreateView(inflater, container, savedInstanceState)
|
||||
|
||||
inventoryRepository.retrieveInAppRewards().subscribe(Action1 { }, RxErrorHandler.handleEmptyError())
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
(layoutManager as GridLayoutManager).spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return if (recyclerAdapter?.getItemViewType(position) ?: 0 < 2) {
|
||||
(getLayoutManager(context) as GridLayoutManager).spanCount
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
view.post { setGridSpanCount(view.width) }
|
||||
val context = context
|
||||
if (context != null) {
|
||||
recyclerView.setBackgroundColor(ContextCompat.getColor(context, R.color.white))
|
||||
}
|
||||
recyclerView.itemAnimator = SafeDefaultItemAnimator()
|
||||
|
||||
inventoryRepository.inAppRewards.subscribe(Action1 {
|
||||
(recyclerAdapter as RewardsRecyclerViewAdapter?)?.updateItemRewards(it)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
override fun getLayoutManager(context: Context?): LinearLayoutManager =
|
||||
GridLayoutManager(context, 4)
|
||||
|
||||
override fun onRefresh() {
|
||||
refreshLayout.isRefreshing = true
|
||||
userRepository.retrieveUser(true, true)
|
||||
.flatMap<List<ShopItem>> { inventoryRepository.retrieveInAppRewards() }
|
||||
.doOnTerminate {
|
||||
refreshLayout.isRefreshing = false
|
||||
}.subscribe(Action1 { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun setGridSpanCount(width: Int) {
|
||||
var spanCount = 0
|
||||
if (context != null && context?.resources != null) {
|
||||
val itemWidth: Float = context?.resources?.getDimension(R.dimen.reward_width) ?: 0f
|
||||
|
||||
spanCount = (width / itemWidth).toInt()
|
||||
}
|
||||
|
||||
if (spanCount == 0) {
|
||||
spanCount = 1
|
||||
}
|
||||
(layoutManager as GridLayoutManager).spanCount = spanCount
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(context: Context?, user: User?, classType: String): RewardsRecyclerviewFragment {
|
||||
val fragment = RewardsRecyclerviewFragment()
|
||||
fragment.retainInstance = true
|
||||
fragment.user = user
|
||||
fragment.classType = classType
|
||||
|
||||
if (context != null) {
|
||||
fragment.tutorialStepIdentifier = "rewards"
|
||||
fragment.tutorialTexts = ArrayList(Arrays.asList(context.getString(R.string.tutorial_rewards_1),
|
||||
context.getString(R.string.tutorial_rewards_2)))
|
||||
}
|
||||
fragment.tutorialCanBeDeferred = false
|
||||
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,388 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.tasks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository;
|
||||
import com.habitrpg.android.habitica.data.TaskRepository;
|
||||
import com.habitrpg.android.habitica.data.UserRepository;
|
||||
import com.habitrpg.android.habitica.events.commands.AddNewTaskCommand;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.helpers.TaskFilterHelper;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
import com.habitrpg.android.habitica.modules.AppModule;
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity;
|
||||
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;
|
||||
import com.habitrpg.android.habitica.ui.adapter.tasks.TaskRecyclerViewAdapter;
|
||||
import com.habitrpg.android.habitica.ui.adapter.tasks.TodosRecyclerViewAdapter;
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseFragment;
|
||||
import com.habitrpg.android.habitica.ui.helpers.RecyclerViewEmptySupport;
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
/**
|
||||
* TaskRecyclerViewFragment
|
||||
* - Creates the View only once
|
||||
* - Adds FAB Icon
|
||||
* - Handles the ScrollPosition - if anyone has a better solution please share it
|
||||
*/
|
||||
public class TaskRecyclerViewFragment extends BaseFragment implements View.OnClickListener, SwipeRefreshLayout.OnRefreshListener {
|
||||
private static final String CLASS_TYPE_KEY = "CLASS_TYPE_KEY";
|
||||
public TaskRecyclerViewAdapter recyclerAdapter;
|
||||
@Inject
|
||||
@Named(AppModule.NAMED_USER_ID)
|
||||
String userID;
|
||||
@Inject
|
||||
ApiClient apiClient;
|
||||
@Inject
|
||||
TaskFilterHelper taskFilterHelper;
|
||||
@Inject
|
||||
UserRepository userRepository;
|
||||
@Inject
|
||||
InventoryRepository inventoryRepository;
|
||||
@Inject
|
||||
TaskRepository taskRepository;
|
||||
|
||||
RecyclerView.LayoutManager layoutManager = null;
|
||||
|
||||
@BindView(R.id.refresh_layout)
|
||||
SwipeRefreshLayout swipeRefreshLayout;
|
||||
@BindView(R.id.recyclerView)
|
||||
public RecyclerViewEmptySupport recyclerView;
|
||||
|
||||
@BindView(R.id.emptyView)
|
||||
ViewGroup emptyView;
|
||||
@BindView(R.id.empty_view_title)
|
||||
TextView emptyViewTitle;
|
||||
@BindView(R.id.empty_view_description)
|
||||
TextView emptyViewDescription;
|
||||
|
||||
@Nullable
|
||||
String classType;
|
||||
@Nullable
|
||||
User user;
|
||||
private View view;
|
||||
@Nullable
|
||||
private ItemTouchHelper.Callback mItemTouchCallback;
|
||||
|
||||
public static TaskRecyclerViewFragment newInstance(Context context, @Nullable User user, String classType) {
|
||||
TaskRecyclerViewFragment fragment = new TaskRecyclerViewFragment();
|
||||
fragment.setRetainInstance(true);
|
||||
fragment.user = user;
|
||||
fragment.classType = classType;
|
||||
List<String> tutorialTexts = null;
|
||||
switch (fragment.classType) {
|
||||
case Task.TYPE_HABIT: {
|
||||
fragment.tutorialStepIdentifier = "habits";
|
||||
tutorialTexts = Arrays.asList(context.getString(R.string.tutorial_overview),
|
||||
context.getString(R.string.tutorial_habits_1),
|
||||
context.getString(R.string.tutorial_habits_2),
|
||||
context.getString(R.string.tutorial_habits_3),
|
||||
context.getString(R.string.tutorial_habits_4));
|
||||
break;
|
||||
}
|
||||
case Task.FREQUENCY_DAILY: {
|
||||
fragment.tutorialStepIdentifier = "dailies";
|
||||
tutorialTexts = Arrays.asList(context.getString(R.string.tutorial_dailies_1),
|
||||
context.getString(R.string.tutorial_dailies_2));
|
||||
break;
|
||||
}
|
||||
case Task.TYPE_TODO: {
|
||||
fragment.tutorialStepIdentifier = "todos";
|
||||
tutorialTexts = Arrays.asList(context.getString(R.string.tutorial_todos_1),
|
||||
context.getString(R.string.tutorial_todos_2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tutorialTexts != null) {
|
||||
fragment.tutorialTexts = new ArrayList<>(tutorialTexts);
|
||||
}
|
||||
fragment.tutorialCanBeDeferred = false;
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
// TODO needs a bit of cleanup
|
||||
public void setInnerAdapter() {
|
||||
if (this.classType != null) {
|
||||
taskRepository.getTasks(this.classType, userID).first().subscribe(tasks -> {
|
||||
int layoutOfType;
|
||||
switch (this.classType) {
|
||||
case Task.TYPE_HABIT:
|
||||
layoutOfType = R.layout.habit_item_card;
|
||||
this.recyclerAdapter = new HabitsRecyclerViewAdapter(tasks, true, layoutOfType, taskFilterHelper);
|
||||
allowReordering();
|
||||
break;
|
||||
case Task.TYPE_DAILY:
|
||||
layoutOfType = R.layout.daily_item_card;
|
||||
int dailyResetOffset = 0;
|
||||
if (user != null) {
|
||||
dailyResetOffset = user.getPreferences().getDayStart();
|
||||
}
|
||||
this.recyclerAdapter = new DailiesRecyclerViewHolder(tasks, true, layoutOfType, dailyResetOffset, taskFilterHelper);
|
||||
allowReordering();
|
||||
break;
|
||||
case Task.TYPE_TODO:
|
||||
layoutOfType = R.layout.todo_item_card;
|
||||
this.recyclerAdapter = new TodosRecyclerViewAdapter(tasks, true, layoutOfType, taskFilterHelper);
|
||||
allowReordering();
|
||||
return;
|
||||
case Task.TYPE_REWARD:
|
||||
layoutOfType = R.layout.reward_item_card;
|
||||
this.recyclerAdapter = new RewardsRecyclerViewAdapter(tasks, getContext(), layoutOfType, user);
|
||||
break;
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
}
|
||||
|
||||
private void allowReordering() {
|
||||
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(mItemTouchCallback);
|
||||
itemTouchHelper.attachToRecyclerView(recyclerView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
if (Task.TYPE_DAILY.equals(classType)) {
|
||||
if (user != null && user.getPreferences().getDailyDueDefaultView()) {
|
||||
taskFilterHelper.setActiveFilter(Task.TYPE_DAILY, Task.FILTER_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
mItemTouchCallback = new ItemTouchHelper.Callback() {
|
||||
private Integer fromPosition = null;
|
||||
|
||||
@Override
|
||||
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
|
||||
super.onSelectedChanged(viewHolder, actionState);
|
||||
if (viewHolder != null) {
|
||||
viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
|
||||
if (fromPosition == null) {
|
||||
fromPosition = viewHolder.getAdapterPosition();
|
||||
}
|
||||
}
|
||||
if (swipeRefreshLayout != null) {
|
||||
swipeRefreshLayout.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
|
||||
recyclerAdapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
|
||||
//taskRepository.swapTaskPosition(viewHolder.getAdapterPosition(), target.getAdapterPosition());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
|
||||
}
|
||||
|
||||
//defines the enabled move directions in each state (idle, swiping, dragging).
|
||||
@Override
|
||||
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
|
||||
return makeFlag(ItemTouchHelper.ACTION_STATE_DRAG,
|
||||
ItemTouchHelper.DOWN | ItemTouchHelper.UP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemViewSwipeEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLongPressDragEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
|
||||
super.clearView(recyclerView, viewHolder);
|
||||
if (swipeRefreshLayout != null) {
|
||||
swipeRefreshLayout.setEnabled(true);
|
||||
}
|
||||
|
||||
if (fromPosition != null) {
|
||||
recyclerAdapter.setIgnoreUpdates(true);
|
||||
taskRepository.updateTaskPosition(fromPosition, viewHolder.getAdapterPosition())
|
||||
.delay(2, TimeUnit.SECONDS)
|
||||
.subscribe(taskPositions -> recyclerAdapter.setIgnoreUpdates(false), RxErrorHandler.handleEmptyError());
|
||||
fromPosition = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (view == null) {
|
||||
view = inflater.inflate(R.layout.fragment_refresh_recyclerview, container, false);
|
||||
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
android.support.v4.app.FragmentActivity context = getActivity();
|
||||
|
||||
layoutManager = recyclerView.getLayoutManager();
|
||||
|
||||
if (layoutManager == null) {
|
||||
layoutManager = getLayoutManager(context);
|
||||
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
}
|
||||
if (recyclerView.getAdapter() == null) {
|
||||
this.setInnerAdapter();
|
||||
}
|
||||
|
||||
int bottomPadding = (int) (recyclerView.getPaddingBottom() + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, getResources().getDisplayMetrics()));
|
||||
recyclerView.setPadding(0, 0, 0, bottomPadding);
|
||||
recyclerView.setItemAnimator(new SafeDefaultItemAnimator());
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener(this);
|
||||
|
||||
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||
super.onScrollStateChanged(recyclerView, newState);
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE && swipeRefreshLayout != null) {
|
||||
swipeRefreshLayout.setEnabled(((MainActivity)getActivity()).isAppBarExpanded());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (this.classType != null) {
|
||||
switch (this.classType) {
|
||||
case Task.TYPE_HABIT: {
|
||||
this.emptyViewTitle.setText(R.string.empty_title_habits);
|
||||
this.emptyViewDescription.setText(R.string.empty_description_habits);
|
||||
break;
|
||||
}
|
||||
case Task.TYPE_DAILY: {
|
||||
this.emptyViewTitle.setText(R.string.empty_title_dailies);
|
||||
this.emptyViewDescription.setText(R.string.empty_description_dailies);
|
||||
break;
|
||||
}
|
||||
case Task.TYPE_TODO: {
|
||||
this.emptyViewTitle.setText(R.string.empty_title_todos);
|
||||
this.emptyViewDescription.setText(R.string.empty_description_todos);
|
||||
break;
|
||||
}
|
||||
case Task.TYPE_REWARD: {
|
||||
this.emptyViewTitle.setText(R.string.empty_title_rewards);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
this.classType = savedInstanceState.getString(CLASS_TYPE_KEY, "");
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected LinearLayoutManager getLayoutManager(FragmentActivity context) {
|
||||
return new LinearLayoutManager(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
userRepository.close();
|
||||
inventoryRepository.close();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
recyclerView.setAdapter((RecyclerView.Adapter) recyclerAdapter);
|
||||
if (recyclerAdapter != null) {
|
||||
recyclerAdapter.filter();
|
||||
}
|
||||
|
||||
if (Task.TYPE_REWARD.equals(getClassName())) {
|
||||
compositeSubscription.add(taskRepository.getTasks(this.getClassName(), userID)
|
||||
.subscribe(tasks -> {
|
||||
if (recyclerAdapter != null) {
|
||||
recyclerAdapter.updateData(tasks);
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(CLASS_TYPE_KEY, this.classType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
AddNewTaskCommand event = new AddNewTaskCommand();
|
||||
event.taskType = this.classType;
|
||||
|
||||
EventBus.getDefault().post(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayedClassName() {
|
||||
return this.classType + super.getDisplayedClassName();
|
||||
}
|
||||
|
||||
String getClassName() {
|
||||
return this.classType != null ? this.classType : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
swipeRefreshLayout.setRefreshing(true);
|
||||
userRepository.retrieveUser(true, true)
|
||||
.doOnTerminate(() -> {
|
||||
if (swipeRefreshLayout != null) {
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
}).subscribe(user1 -> {}, RxErrorHandler.handleEmptyError());
|
||||
}
|
||||
|
||||
public void setActiveFilter(String activeFilter) {
|
||||
if (classType != null) {
|
||||
taskFilterHelper.setActiveFilter(classType, activeFilter);
|
||||
}
|
||||
recyclerAdapter.filter();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,308 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.tasks
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.support.v4.widget.SwipeRefreshLayout
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.support.v7.widget.helper.ItemTouchHelper
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.events.commands.AddNewTaskCommand
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.TaskFilterHelper
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
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
|
||||
import com.habitrpg.android.habitica.ui.adapter.tasks.TaskRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.adapter.tasks.TodosRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import kotlinx.android.synthetic.main.fragment_refresh_recyclerview.*
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import rx.functions.Action1
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
open class TaskRecyclerViewFragment : BaseFragment(), View.OnClickListener, SwipeRefreshLayout.OnRefreshListener {
|
||||
var recyclerAdapter: TaskRecyclerViewAdapter? = null
|
||||
@field:[Inject Named(AppModule.NAMED_USER_ID)]
|
||||
lateinit var userID: String
|
||||
@Inject
|
||||
lateinit var apiClient: ApiClient
|
||||
@Inject
|
||||
lateinit var taskFilterHelper: TaskFilterHelper
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
@Inject
|
||||
lateinit var inventoryRepository: InventoryRepository
|
||||
@Inject
|
||||
lateinit var taskRepository: TaskRepository
|
||||
|
||||
internal var layoutManager: RecyclerView.LayoutManager? = null
|
||||
|
||||
internal var classType: String? = null
|
||||
internal var user: User? = null
|
||||
private var mItemTouchCallback: ItemTouchHelper.Callback? = null
|
||||
|
||||
internal val className: String
|
||||
get() = this.classType ?: ""
|
||||
|
||||
// TODO needs a bit of cleanup
|
||||
private fun setInnerAdapter() {
|
||||
val adapter: RecyclerView.Adapter<*>? = when (this.classType) {
|
||||
Task.TYPE_HABIT -> {
|
||||
HabitsRecyclerViewAdapter(null, true, R.layout.habit_item_card, taskFilterHelper)
|
||||
}
|
||||
Task.TYPE_DAILY -> {
|
||||
var dailyResetOffset = 0
|
||||
if (user != null) {
|
||||
dailyResetOffset = user?.preferences?.dayStart ?: 0
|
||||
}
|
||||
DailiesRecyclerViewHolder(null, true, R.layout.daily_item_card, dailyResetOffset, taskFilterHelper)
|
||||
}
|
||||
Task.TYPE_TODO -> {
|
||||
TodosRecyclerViewAdapter(null, true, R.layout.todo_item_card, taskFilterHelper)
|
||||
}
|
||||
Task.TYPE_REWARD -> {
|
||||
RewardsRecyclerViewAdapter(null, context, R.layout.reward_item_card, user)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (classType != Task.TYPE_REWARD) {
|
||||
allowReordering()
|
||||
}
|
||||
|
||||
recyclerAdapter = adapter as TaskRecyclerViewAdapter
|
||||
recyclerView.adapter = adapter
|
||||
|
||||
if (this.classType != null) {
|
||||
taskRepository.getTasks(this.classType ?: "", userID).first().subscribe(Action1 { this.recyclerAdapter?.updateData(it) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
private fun allowReordering() {
|
||||
val itemTouchHelper = ItemTouchHelper(mItemTouchCallback)
|
||||
itemTouchHelper.attachToRecyclerView(recyclerView)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
|
||||
if (Task.TYPE_DAILY == classType) {
|
||||
if (user != null && user?.preferences?.dailyDueDefaultView == true) {
|
||||
taskFilterHelper.setActiveFilter(Task.TYPE_DAILY, Task.FILTER_ACTIVE)
|
||||
}
|
||||
}
|
||||
|
||||
mItemTouchCallback = object : ItemTouchHelper.Callback() {
|
||||
private var fromPosition: Int? = null
|
||||
|
||||
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
|
||||
super.onSelectedChanged(viewHolder, actionState)
|
||||
if (viewHolder != null) {
|
||||
viewHolder.itemView.setBackgroundColor(Color.LTGRAY)
|
||||
if (fromPosition == null) {
|
||||
fromPosition = viewHolder.adapterPosition
|
||||
}
|
||||
}
|
||||
refreshLayout.isEnabled = false
|
||||
}
|
||||
|
||||
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
|
||||
recyclerAdapter?.notifyItemMoved(viewHolder.adapterPosition, target.adapterPosition)
|
||||
//taskRepository.swapTaskPosition(viewHolder.getAdapterPosition(), target.getAdapterPosition());
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
|
||||
|
||||
//defines the enabled move directions in each state (idle, swiping, dragging).
|
||||
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
|
||||
return ItemTouchHelper.Callback.makeFlag(ItemTouchHelper.ACTION_STATE_DRAG,
|
||||
ItemTouchHelper.DOWN or ItemTouchHelper.UP)
|
||||
}
|
||||
|
||||
override fun isItemViewSwipeEnabled(): Boolean = false
|
||||
|
||||
override fun isLongPressDragEnabled(): Boolean = true
|
||||
|
||||
override fun clearView(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder) {
|
||||
super.clearView(recyclerView, viewHolder)
|
||||
refreshLayout?.isEnabled = true
|
||||
|
||||
val fromPosition = fromPosition
|
||||
if (fromPosition != null) {
|
||||
recyclerAdapter?.ignoreUpdates = true
|
||||
taskRepository.updateTaskPosition(classType ?: "", fromPosition, viewHolder.adapterPosition)
|
||||
.delay(1, TimeUnit.SECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(Action1 { recyclerAdapter?.ignoreUpdates = false
|
||||
recyclerAdapter?.notifyDataSetChanged()}, RxErrorHandler.handleEmptyError())
|
||||
this.fromPosition = null
|
||||
}
|
||||
}
|
||||
}
|
||||
if (savedInstanceState != null) {
|
||||
this.classType = savedInstanceState.getString(CLASS_TYPE_KEY, "")
|
||||
}
|
||||
|
||||
return inflater.inflate(R.layout.fragment_refresh_recyclerview, container, false)
|
||||
}
|
||||
|
||||
protected open fun getLayoutManager(context: Context?): LinearLayoutManager = LinearLayoutManager(context)
|
||||
|
||||
override fun onDestroy() {
|
||||
userRepository.close()
|
||||
inventoryRepository.close()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun injectFragment(component: AppComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
recyclerView.adapter = recyclerAdapter as RecyclerView.Adapter<*>?
|
||||
recyclerAdapter?.filter()
|
||||
|
||||
layoutManager = recyclerView.layoutManager
|
||||
|
||||
if (layoutManager == null) {
|
||||
layoutManager = getLayoutManager(context)
|
||||
|
||||
recyclerView.layoutManager = layoutManager
|
||||
}
|
||||
if (recyclerView.adapter == null) {
|
||||
this.setInnerAdapter()
|
||||
}
|
||||
|
||||
val bottomPadding = (recyclerView.paddingBottom + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60f, resources.displayMetrics)).toInt()
|
||||
recyclerView.setPadding(0, 0, 0, bottomPadding)
|
||||
recyclerView.itemAnimator = SafeDefaultItemAnimator()
|
||||
|
||||
refreshLayout.setOnRefreshListener(this)
|
||||
|
||||
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
refreshLayout?.isEnabled = (activity as MainActivity).isAppBarExpanded
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (this.classType != null) {
|
||||
when (this.classType) {
|
||||
Task.TYPE_HABIT -> {
|
||||
this.emptyViewTitle.setText(R.string.empty_title_habits)
|
||||
this.emptyViewDescription.setText(R.string.empty_description_habits)
|
||||
}
|
||||
Task.TYPE_DAILY -> {
|
||||
this.emptyViewTitle.setText(R.string.empty_title_dailies)
|
||||
this.emptyViewDescription.setText(R.string.empty_description_dailies)
|
||||
}
|
||||
Task.TYPE_TODO -> {
|
||||
this.emptyViewTitle.setText(R.string.empty_title_todos)
|
||||
this.emptyViewDescription.setText(R.string.empty_description_todos)
|
||||
}
|
||||
Task.TYPE_REWARD -> {
|
||||
this.emptyViewTitle.setText(R.string.empty_title_rewards)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Task.TYPE_REWARD == className) {
|
||||
compositeSubscription.add(taskRepository.getTasks(this.className, userID)
|
||||
.subscribe(Action1 { recyclerAdapter?.updateData(it) }, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putString(CLASS_TYPE_KEY, this.classType)
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
val event = AddNewTaskCommand()
|
||||
event.taskType = this.classType
|
||||
|
||||
EventBus.getDefault().post(event)
|
||||
}
|
||||
|
||||
override fun getDisplayedClassName(): String = this.classType + super.getDisplayedClassName()
|
||||
|
||||
override fun onRefresh() {
|
||||
refreshLayout.isRefreshing = true
|
||||
userRepository.retrieveUser(true, true)
|
||||
.doOnTerminate {
|
||||
refreshLayout.isRefreshing = false
|
||||
}.subscribe(Action1 { }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
fun setActiveFilter(activeFilter: String) {
|
||||
if (classType != null) {
|
||||
taskFilterHelper.setActiveFilter(classType, activeFilter)
|
||||
}
|
||||
recyclerAdapter?.filter()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val CLASS_TYPE_KEY = "CLASS_TYPE_KEY"
|
||||
|
||||
fun newInstance(context: Context?, user: User?, classType: String): TaskRecyclerViewFragment {
|
||||
val fragment = TaskRecyclerViewFragment()
|
||||
fragment.retainInstance = true
|
||||
fragment.user = user
|
||||
fragment.classType = classType
|
||||
var tutorialTexts: List<String>? = null
|
||||
if (context != null) {
|
||||
when (fragment.classType) {
|
||||
Task.TYPE_HABIT -> {
|
||||
fragment.tutorialStepIdentifier = "habits"
|
||||
tutorialTexts = Arrays.asList(context.getString(R.string.tutorial_overview),
|
||||
context.getString(R.string.tutorial_habits_1),
|
||||
context.getString(R.string.tutorial_habits_2),
|
||||
context.getString(R.string.tutorial_habits_3),
|
||||
context.getString(R.string.tutorial_habits_4))
|
||||
}
|
||||
Task.FREQUENCY_DAILY -> {
|
||||
fragment.tutorialStepIdentifier = "dailies"
|
||||
tutorialTexts = Arrays.asList(context.getString(R.string.tutorial_dailies_1),
|
||||
context.getString(R.string.tutorial_dailies_2))
|
||||
}
|
||||
Task.TYPE_TODO -> {
|
||||
fragment.tutorialStepIdentifier = "todos"
|
||||
tutorialTexts = Arrays.asList(context.getString(R.string.tutorial_todos_1),
|
||||
context.getString(R.string.tutorial_todos_2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tutorialTexts != null) {
|
||||
fragment.tutorialTexts = ArrayList(tutorialTexts)
|
||||
}
|
||||
fragment.tutorialCanBeDeferred = false
|
||||
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,475 +0,0 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.tasks;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
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 com.github.clans.fab.FloatingActionButton;
|
||||
import com.github.clans.fab.FloatingActionMenu;
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication;
|
||||
import com.habitrpg.android.habitica.R;
|
||||
import com.habitrpg.android.habitica.components.AppComponent;
|
||||
import com.habitrpg.android.habitica.data.TagRepository;
|
||||
import com.habitrpg.android.habitica.events.TaskTappedEvent;
|
||||
import com.habitrpg.android.habitica.events.commands.AddNewTaskCommand;
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler;
|
||||
import com.habitrpg.android.habitica.helpers.TaskFilterHelper;
|
||||
import com.habitrpg.android.habitica.models.TutorialStep;
|
||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||
import com.habitrpg.android.habitica.models.user.User;
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity;
|
||||
import com.habitrpg.android.habitica.ui.activities.TaskFormActivity;
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment;
|
||||
import com.habitrpg.android.habitica.ui.views.tasks.TaskFilterDialog;
|
||||
import com.roughike.bottombar.BottomBarTab;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class TasksFragment extends BaseMainFragment {
|
||||
|
||||
private static final int TASK_CREATED_RESULT = 1;
|
||||
private static final int TASK_UPDATED_RESULT = 2;
|
||||
|
||||
public ViewPager viewPager;
|
||||
@Inject
|
||||
public TaskFilterHelper taskFilterHelper; // This will be used for this fragment. Currently being used to help filtering
|
||||
@Inject
|
||||
TagRepository tagRepository;
|
||||
MenuItem refreshItem;
|
||||
FloatingActionMenu floatingMenu;
|
||||
Map<Integer, TaskRecyclerViewFragment> viewFragmentsDictionary = new WeakHashMap<>();
|
||||
|
||||
private boolean displayingTaskForm;
|
||||
@Nullable
|
||||
private MenuItem filterMenuItem;
|
||||
|
||||
public void setActivity(MainActivity activity) {
|
||||
super.setActivity(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
this.usesTabLayout = false;
|
||||
this.usesBottomNavigation = true;
|
||||
this.displayingTaskForm = false;
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
View v = inflater.inflate(R.layout.fragment_viewpager, container, false);
|
||||
|
||||
|
||||
viewPager = v.findViewById(R.id.viewPager);
|
||||
View view = inflater.inflate(R.layout.floating_menu_tasks, floatingMenuWrapper, true);
|
||||
if (FloatingActionMenu.class.equals(view.getClass())) {
|
||||
floatingMenu = (FloatingActionMenu) view;
|
||||
} else {
|
||||
ViewGroup frame = (ViewGroup) view;
|
||||
floatingMenu = frame.findViewById(R.id.fab_menu);
|
||||
}
|
||||
FloatingActionButton habit_fab = floatingMenu.findViewById(R.id.fab_new_habit);
|
||||
habit_fab.setOnClickListener(v1 -> openNewTaskActivity(Task.TYPE_HABIT));
|
||||
FloatingActionButton daily_fab = floatingMenu.findViewById(R.id.fab_new_daily);
|
||||
daily_fab.setOnClickListener(v1 -> openNewTaskActivity(Task.TYPE_DAILY));
|
||||
FloatingActionButton todo_fab = floatingMenu.findViewById(R.id.fab_new_todo);
|
||||
todo_fab.setOnClickListener(v1 -> openNewTaskActivity(Task.TYPE_TODO));
|
||||
FloatingActionButton reward_fab = floatingMenu.findViewById(R.id.fab_new_reward);
|
||||
reward_fab.setOnClickListener(v1 -> openNewTaskActivity(Task.TYPE_REWARD));
|
||||
floatingMenu.setOnMenuButtonLongClickListener(this::onFloatingMenuLongClicked);
|
||||
|
||||
loadTaskLists();
|
||||
|
||||
if (bottomNavigation != null) {
|
||||
bottomNavigation.setBadgesHideWhenActive(true);
|
||||
bottomNavigation.setOnTabSelectListener(tabId -> {
|
||||
if (tabId == R.id.tab_habits) {
|
||||
viewPager.setCurrentItem(0);
|
||||
} else if (tabId == R.id.tab_dailies) {
|
||||
viewPager.setCurrentItem(1);
|
||||
} else if (tabId == R.id.tab_todos) {
|
||||
viewPager.setCurrentItem(2);
|
||||
} else if (tabId == R.id.tab_rewards) {
|
||||
viewPager.setCurrentItem(3);
|
||||
}
|
||||
updateBottomBarBadges();
|
||||
});
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
tagRepository.close();
|
||||
if (bottomNavigation != null) {
|
||||
bottomNavigation.removeOnTabSelectListener();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private boolean onFloatingMenuLongClicked(View view) {
|
||||
TaskRecyclerViewFragment currentFragment = getActiveFragment();
|
||||
if (currentFragment != null) {
|
||||
String className = currentFragment.getClassName();
|
||||
openNewTaskActivity(className);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(AppComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.menu_main_activity, menu);
|
||||
|
||||
filterMenuItem = menu.findItem(R.id.action_search);
|
||||
updateFilterIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
|
||||
switch (id) {
|
||||
case R.id.action_search:
|
||||
showFilterDialog();
|
||||
return true;
|
||||
case R.id.action_reload:
|
||||
refreshItem = item;
|
||||
refresh();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void showFilterDialog() {
|
||||
TaskFilterDialog dialog = new TaskFilterDialog(getContext(), HabiticaBaseApplication.getComponent());
|
||||
if (user != null) {
|
||||
dialog.setTags(user.getTags().createSnapshot());
|
||||
}
|
||||
dialog.setActiveTags(taskFilterHelper.getTags());
|
||||
if (getActiveFragment() != null) {
|
||||
String taskType = getActiveFragment().classType;
|
||||
if (taskType != null) {
|
||||
dialog.setTaskType(taskType, taskFilterHelper.getActiveFilter(taskType));
|
||||
}
|
||||
}
|
||||
dialog.setListener((activeTaskFilter, activeTags) -> {
|
||||
if (viewFragmentsDictionary == null) {
|
||||
return;
|
||||
}
|
||||
int activePos = viewPager.getCurrentItem();
|
||||
if (activePos >= 1 && viewFragmentsDictionary.get(activePos-1) != null && activePos >= 1 && viewFragmentsDictionary.get(activePos-1).recyclerAdapter != null) {
|
||||
viewFragmentsDictionary.get(activePos-1).recyclerAdapter.filter();
|
||||
}
|
||||
if (activePos < viewPager.getAdapter().getCount()-1 && viewFragmentsDictionary.get(activePos+1) != null && viewFragmentsDictionary.get(activePos+1).recyclerAdapter != null) {
|
||||
viewFragmentsDictionary.get(activePos+1).recyclerAdapter.filter();
|
||||
}
|
||||
if (getActiveFragment() != null) {
|
||||
getActiveFragment().setActiveFilter(activeTaskFilter);
|
||||
}
|
||||
taskFilterHelper.setTags(activeTags);
|
||||
updateFilterIcon();
|
||||
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
if (getActiveFragment() != null) {
|
||||
getActiveFragment().onRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadTaskLists() {
|
||||
android.support.v4.app.FragmentManager fragmentManager = getChildFragmentManager();
|
||||
|
||||
viewPager.setAdapter(new FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
TaskRecyclerViewFragment fragment;
|
||||
|
||||
switch (position) {
|
||||
case 0:
|
||||
fragment = TaskRecyclerViewFragment.newInstance(getContext(), user, Task.TYPE_HABIT);
|
||||
break;
|
||||
case 1:
|
||||
fragment = TaskRecyclerViewFragment.newInstance(getContext(), user, Task.TYPE_DAILY);
|
||||
break;
|
||||
case 3:
|
||||
fragment = RewardsRecyclerviewFragment.newInstance(getContext(), user, Task.TYPE_REWARD);
|
||||
break;
|
||||
default:
|
||||
fragment = TaskRecyclerViewFragment.newInstance(getContext(), user, Task.TYPE_TODO);
|
||||
}
|
||||
|
||||
viewFragmentsDictionary.put(position, fragment);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
if (activity != null) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return activity.getString(R.string.habits);
|
||||
case 1:
|
||||
return activity.getString(R.string.dailies);
|
||||
case 2:
|
||||
return activity.getString(R.string.todos);
|
||||
case 3:
|
||||
return activity.getString(R.string.rewards);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
if (bottomNavigation != null) {
|
||||
bottomNavigation.selectTabAtPosition(position);
|
||||
}
|
||||
updateFilterIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateFilterIcon() {
|
||||
if (filterMenuItem == null) {
|
||||
return;
|
||||
}
|
||||
int filterCount = 0;
|
||||
if (getActiveFragment() != null) {
|
||||
filterCount = taskFilterHelper.howMany(getActiveFragment().classType);
|
||||
}
|
||||
if (filterCount == 0) {
|
||||
filterMenuItem.setIcon(R.drawable.ic_action_filter_list);
|
||||
} else {
|
||||
filterMenuItem.setIcon(R.drawable.ic_filters_active);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBottomBarBadges() {
|
||||
if (bottomNavigation == null) {
|
||||
return;
|
||||
}
|
||||
tutorialRepository.getTutorialSteps(Arrays.asList("habits", "dailies", "todos", "rewards")).subscribe(tutorialSteps -> {
|
||||
List<String> activeTutorialFragments = new ArrayList<>();
|
||||
for (TutorialStep step : tutorialSteps) {
|
||||
int id = -1;
|
||||
String taskType = null;
|
||||
switch (step.getIdentifier()) {
|
||||
case "habits":
|
||||
id = R.id.tab_habits;
|
||||
taskType = Task.TYPE_HABIT;
|
||||
break;
|
||||
case "dailies":
|
||||
id = R.id.tab_dailies;
|
||||
taskType = Task.TYPE_DAILY;
|
||||
break;
|
||||
case "todos":
|
||||
id = R.id.tab_todos;
|
||||
taskType = Task.TYPE_TODO;
|
||||
break;
|
||||
case "rewards":
|
||||
id = R.id.tab_rewards;
|
||||
taskType = Task.TYPE_REWARD;
|
||||
break;
|
||||
}
|
||||
BottomBarTab tab = bottomNavigation.getTabWithId(id);
|
||||
if (step.shouldDisplay()) {
|
||||
tab.setBadgeCount(1);
|
||||
activeTutorialFragments.add(taskType);
|
||||
} else {
|
||||
tab.removeBadge();
|
||||
}
|
||||
}
|
||||
if (activeTutorialFragments.size() == 1) {
|
||||
TaskRecyclerViewFragment fragment = viewFragmentsDictionary.get(indexForTaskType(activeTutorialFragments.get(0)));
|
||||
if (fragment != null && fragment.tutorialTexts != null && getContext() != null) {
|
||||
String finalText = getContext().getString(R.string.tutorial_tasks_complete);
|
||||
if (!fragment.tutorialTexts.contains(finalText)) {
|
||||
fragment.tutorialTexts.add(finalText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError());
|
||||
BottomBarTab tab = bottomNavigation.getTabWithId(R.id.tab_dailies);
|
||||
}
|
||||
// endregion
|
||||
|
||||
//region Events
|
||||
public void updateUserData(User user) {
|
||||
super.updateUserData(user);
|
||||
}
|
||||
|
||||
private void openNewTaskActivity(String type) {
|
||||
if (this.displayingTaskForm) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean allocationMode = false;
|
||||
if (user != null && user.getPreferences() != null) {
|
||||
allocationMode = user.getPreferences().hasTaskBasedAllocation();
|
||||
}
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, type);
|
||||
bundle.putString(TaskFormActivity.USER_ID_KEY, this.user != null ? this.user.getId() : null);
|
||||
bundle.putBoolean(TaskFormActivity.ALLOCATION_MODE_KEY, allocationMode);
|
||||
|
||||
Intent intent = new Intent(activity, TaskFormActivity.class);
|
||||
intent.putExtras(bundle);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
if (this.isAdded()) {
|
||||
this.displayingTaskForm = true;
|
||||
startActivityForResult(intent, TASK_CREATED_RESULT);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TaskRecyclerViewFragment getActiveFragment() {
|
||||
|
||||
return viewFragmentsDictionary.get(viewPager.getCurrentItem());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(TaskTappedEvent event) {
|
||||
if (this.displayingTaskForm) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean allocationMode = false;
|
||||
if (user != null && user.getPreferences() != null) {
|
||||
allocationMode = user.getPreferences().hasTaskBasedAllocation();
|
||||
}
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, event.Task.getType());
|
||||
bundle.putString(TaskFormActivity.TASK_ID_KEY, event.Task.getId());
|
||||
bundle.putString(TaskFormActivity.USER_ID_KEY, this.user != null ? this.user.getId() : null);
|
||||
bundle.putBoolean(TaskFormActivity.ALLOCATION_MODE_KEY, allocationMode);
|
||||
|
||||
Intent intent = new Intent(activity, TaskFormActivity.class);
|
||||
intent.putExtras(bundle);
|
||||
this.displayingTaskForm = true;
|
||||
if (isAdded()) {
|
||||
startActivityForResult(intent, TASK_UPDATED_RESULT);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(AddNewTaskCommand event) {
|
||||
openNewTaskActivity(event.taskType.toLowerCase(Locale.US));
|
||||
}
|
||||
|
||||
//endregion Events
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
switch (requestCode) {
|
||||
case (TASK_CREATED_RESULT):
|
||||
this.displayingTaskForm = false;
|
||||
onTaskCreatedResult(resultCode, data);
|
||||
break;
|
||||
case (TASK_UPDATED_RESULT):
|
||||
this.displayingTaskForm = false;
|
||||
break;
|
||||
}
|
||||
if (floatingMenu != null) {
|
||||
floatingMenu.close(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void onTaskCreatedResult(int resultCode, Intent data) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
String taskType = data.getStringExtra(TaskFormActivity.TASK_TYPE_KEY);
|
||||
switchToTaskTab(taskType);
|
||||
}
|
||||
}
|
||||
|
||||
private void switchToTaskTab(String taskType) {
|
||||
int index = indexForTaskType(taskType);
|
||||
if (viewPager != null && index != -1) {
|
||||
viewPager.setCurrentItem(index);
|
||||
updateBottomBarBadges();
|
||||
}
|
||||
}
|
||||
|
||||
private int indexForTaskType(String taskType) {
|
||||
if (taskType != null) {
|
||||
for (int index = 0; index < viewFragmentsDictionary.size(); index++) {
|
||||
TaskRecyclerViewFragment fragment = viewFragmentsDictionary.get(index);
|
||||
if (fragment != null && taskType.equals(fragment.getClassName())) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getDisplayedClassName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String customTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addToBackStack() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,389 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.tasks
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.support.v4.view.ViewPager
|
||||
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 com.github.clans.fab.FloatingActionButton
|
||||
import com.github.clans.fab.FloatingActionMenu
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.TagRepository
|
||||
import com.habitrpg.android.habitica.events.TaskTappedEvent
|
||||
import com.habitrpg.android.habitica.events.commands.AddNewTaskCommand
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.TaskFilterHelper
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.android.habitica.ui.activities.TaskFormActivity
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.views.tasks.TaskFilterDialog
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import rx.functions.Action1
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class TasksFragment : BaseMainFragment() {
|
||||
|
||||
var viewPager: ViewPager? = null
|
||||
@Inject
|
||||
lateinit var taskFilterHelper: TaskFilterHelper
|
||||
@Inject
|
||||
lateinit var tagRepository: TagRepository
|
||||
|
||||
internal var refreshItem: MenuItem? = null
|
||||
internal var floatingMenu: FloatingActionMenu? = null
|
||||
internal var viewFragmentsDictionary: MutableMap<Int, TaskRecyclerViewFragment>? = WeakHashMap()
|
||||
|
||||
private var displayingTaskForm: Boolean = false
|
||||
private var filterMenuItem: MenuItem? = null
|
||||
|
||||
private val activeFragment: TaskRecyclerViewFragment?
|
||||
get() = viewFragmentsDictionary?.get(viewPager?.currentItem)
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
||||
this.usesTabLayout = false
|
||||
this.usesBottomNavigation = true
|
||||
this.displayingTaskForm = false
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
val v = inflater.inflate(R.layout.fragment_viewpager, container, false)
|
||||
|
||||
|
||||
viewPager = v.findViewById(R.id.viewPager)
|
||||
val view = inflater.inflate(R.layout.floating_menu_tasks, floatingMenuWrapper, true)
|
||||
floatingMenu = if (FloatingActionMenu::class.java == view.javaClass) {
|
||||
view as FloatingActionMenu
|
||||
} else {
|
||||
val frame = view as ViewGroup
|
||||
frame.findViewById(R.id.fab_menu)
|
||||
}
|
||||
val habitFab = floatingMenu?.findViewById<FloatingActionButton>(R.id.fab_new_habit)
|
||||
habitFab?.setOnClickListener { openNewTaskActivity(Task.TYPE_HABIT) }
|
||||
val dailyFab = floatingMenu?.findViewById<FloatingActionButton>(R.id.fab_new_daily)
|
||||
dailyFab?.setOnClickListener { openNewTaskActivity(Task.TYPE_DAILY) }
|
||||
val todoFab = floatingMenu?.findViewById<FloatingActionButton>(R.id.fab_new_todo)
|
||||
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) }
|
||||
|
||||
loadTaskLists()
|
||||
|
||||
bottomNavigation?.setBadgesHideWhenActive(true)
|
||||
bottomNavigation?.setOnTabSelectListener { tabId ->
|
||||
when (tabId) {
|
||||
R.id.tab_habits -> viewPager?.currentItem = 0
|
||||
R.id.tab_dailies -> viewPager?.currentItem = 1
|
||||
R.id.tab_todos -> viewPager?.currentItem = 2
|
||||
R.id.tab_rewards -> viewPager?.currentItem = 3
|
||||
}
|
||||
updateBottomBarBadges()
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
tagRepository.close()
|
||||
bottomNavigation?.removeOnTabSelectListener()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun onFloatingMenuLongClicked(view: View): Boolean {
|
||||
val currentFragment = activeFragment
|
||||
if (currentFragment != null) {
|
||||
val className = currentFragment.className
|
||||
openNewTaskActivity(className)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun injectFragment(component: AppComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.menu_main_activity, menu)
|
||||
|
||||
filterMenuItem = menu.findItem(R.id.action_search)
|
||||
updateFilterIcon()
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
val id = item.itemId
|
||||
|
||||
when (id) {
|
||||
R.id.action_search -> {
|
||||
showFilterDialog()
|
||||
return true
|
||||
}
|
||||
R.id.action_reload -> {
|
||||
refreshItem = item
|
||||
refresh()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun showFilterDialog() {
|
||||
val dialog = TaskFilterDialog(context, HabiticaBaseApplication.getComponent())
|
||||
if (user != null) {
|
||||
dialog.setTags(user?.tags?.createSnapshot())
|
||||
}
|
||||
dialog.setActiveTags(taskFilterHelper.tags)
|
||||
if (activeFragment != null) {
|
||||
val taskType = activeFragment?.classType
|
||||
if (taskType != null) {
|
||||
dialog.setTaskType(taskType, taskFilterHelper.getActiveFilter(taskType))
|
||||
}
|
||||
}
|
||||
dialog.setListener { activeTaskFilter, activeTags ->
|
||||
if (viewFragmentsDictionary == null) {
|
||||
return@setListener
|
||||
}
|
||||
val activePos = viewPager?.currentItem ?: 0
|
||||
if (activePos >= 1 && viewFragmentsDictionary?.get(activePos - 1) != null && activePos >= 1 && viewFragmentsDictionary?.get(activePos - 1)?.recyclerAdapter != null) {
|
||||
viewFragmentsDictionary?.get(activePos - 1)?.recyclerAdapter?.filter()
|
||||
}
|
||||
if (activePos < viewPager?.adapter?.count ?: 0 - 1 && viewFragmentsDictionary?.get(activePos + 1) != null && viewFragmentsDictionary?.get(activePos + 1)?.recyclerAdapter != null) {
|
||||
viewFragmentsDictionary?.get(activePos + 1)?.recyclerAdapter?.filter()
|
||||
}
|
||||
activeFragment?.setActiveFilter(activeTaskFilter)
|
||||
taskFilterHelper.tags = activeTags
|
||||
updateFilterIcon()
|
||||
|
||||
}
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private fun refresh() {
|
||||
activeFragment?.onRefresh()
|
||||
}
|
||||
|
||||
private fun loadTaskLists() {
|
||||
val fragmentManager = childFragmentManager
|
||||
|
||||
viewPager?.adapter = object : FragmentPagerAdapter(fragmentManager) {
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
val fragment: TaskRecyclerViewFragment = when (position) {
|
||||
0 -> TaskRecyclerViewFragment.newInstance(context, user, Task.TYPE_HABIT)
|
||||
1 -> TaskRecyclerViewFragment.newInstance(context, user, Task.TYPE_DAILY)
|
||||
3 -> RewardsRecyclerviewFragment.newInstance(context, user, Task.TYPE_REWARD)
|
||||
else -> TaskRecyclerViewFragment.newInstance(context, user, Task.TYPE_TODO)
|
||||
}
|
||||
|
||||
viewFragmentsDictionary?.put(position, fragment)
|
||||
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun getCount(): Int = 4
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence? = when (position) {
|
||||
0 -> activity?.getString(R.string.habits)
|
||||
1 -> activity?.getString(R.string.dailies)
|
||||
2 -> activity?.getString(R.string.todos)
|
||||
3 -> activity?.getString(R.string.rewards)
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
viewPager?.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
bottomNavigation?.selectTabAtPosition(position)
|
||||
updateFilterIcon()
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun updateFilterIcon() {
|
||||
if (filterMenuItem == null) {
|
||||
return
|
||||
}
|
||||
var filterCount = 0
|
||||
if (activeFragment != null) {
|
||||
filterCount = taskFilterHelper.howMany(activeFragment?.classType)
|
||||
}
|
||||
if (filterCount == 0) {
|
||||
filterMenuItem?.setIcon(R.drawable.ic_action_filter_list)
|
||||
} else {
|
||||
filterMenuItem?.setIcon(R.drawable.ic_filters_active)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateBottomBarBadges() {
|
||||
if (bottomNavigation == null) {
|
||||
return
|
||||
}
|
||||
tutorialRepository.getTutorialSteps(Arrays.asList("habits", "dailies", "todos", "rewards")).subscribe(Action1 { tutorialSteps ->
|
||||
val activeTutorialFragments = ArrayList<String>()
|
||||
for (step in tutorialSteps) {
|
||||
var id = -1
|
||||
val taskType = when (step.identifier) {
|
||||
"habits" -> {
|
||||
id = R.id.tab_habits
|
||||
Task.TYPE_HABIT
|
||||
}
|
||||
"dailies" -> {
|
||||
id = R.id.tab_dailies
|
||||
Task.TYPE_DAILY
|
||||
}
|
||||
"todos" -> {
|
||||
id = R.id.tab_todos
|
||||
Task.TYPE_TODO
|
||||
}
|
||||
"rewards" -> {
|
||||
id = R.id.tab_rewards
|
||||
Task.TYPE_REWARD
|
||||
}
|
||||
else -> ""
|
||||
}
|
||||
val tab = bottomNavigation?.getTabWithId(id)
|
||||
if (step.shouldDisplay()) {
|
||||
tab?.setBadgeCount(1)
|
||||
activeTutorialFragments.add(taskType)
|
||||
} else {
|
||||
tab?.removeBadge()
|
||||
}
|
||||
}
|
||||
if (activeTutorialFragments.size == 1) {
|
||||
val fragment = viewFragmentsDictionary?.get(indexForTaskType(activeTutorialFragments[0]))
|
||||
if (fragment?.tutorialTexts != null && context != null) {
|
||||
val finalText = context?.getString(R.string.tutorial_tasks_complete)
|
||||
if (!fragment.tutorialTexts.contains(finalText)) {
|
||||
fragment.tutorialTexts.add(finalText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
// endregion
|
||||
|
||||
private fun openNewTaskActivity(type: String) {
|
||||
if (this.displayingTaskForm) {
|
||||
return
|
||||
}
|
||||
|
||||
val allocationMode = user?.preferences?.hasTaskBasedAllocation() ?: false
|
||||
|
||||
val bundle = Bundle()
|
||||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, type)
|
||||
bundle.putString(TaskFormActivity.USER_ID_KEY, if (this.user != null) this.user?.id else null)
|
||||
bundle.putBoolean(TaskFormActivity.ALLOCATION_MODE_KEY, allocationMode)
|
||||
|
||||
val intent = Intent(activity, TaskFormActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
|
||||
if (this.isAdded) {
|
||||
this.displayingTaskForm = true
|
||||
startActivityForResult(intent, TASK_CREATED_RESULT)
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: TaskTappedEvent) {
|
||||
if (this.displayingTaskForm) {
|
||||
return
|
||||
}
|
||||
|
||||
val allocationMode = user?.preferences?.hasTaskBasedAllocation() ?: false
|
||||
|
||||
val bundle = Bundle()
|
||||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, event.Task.type)
|
||||
bundle.putString(TaskFormActivity.TASK_ID_KEY, event.Task.id)
|
||||
bundle.putString(TaskFormActivity.USER_ID_KEY, if (this.user != null) this.user?.id else null)
|
||||
bundle.putBoolean(TaskFormActivity.ALLOCATION_MODE_KEY, allocationMode)
|
||||
|
||||
val intent = Intent(activity, TaskFormActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
this.displayingTaskForm = true
|
||||
if (isAdded) {
|
||||
startActivityForResult(intent, TASK_UPDATED_RESULT)
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(event: AddNewTaskCommand) {
|
||||
openNewTaskActivity(event.taskType.toLowerCase(Locale.US))
|
||||
}
|
||||
|
||||
//endregion Events
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
when (requestCode) {
|
||||
TASK_CREATED_RESULT -> {
|
||||
this.displayingTaskForm = false
|
||||
onTaskCreatedResult(resultCode, data)
|
||||
}
|
||||
TASK_UPDATED_RESULT -> this.displayingTaskForm = false
|
||||
}
|
||||
floatingMenu?.close(true)
|
||||
}
|
||||
|
||||
private fun onTaskCreatedResult(resultCode: Int, data: Intent?) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
val taskType = data?.getStringExtra(TaskFormActivity.TASK_TYPE_KEY)
|
||||
if (taskType != null) {
|
||||
switchToTaskTab(taskType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun switchToTaskTab(taskType: String) {
|
||||
val index = indexForTaskType(taskType)
|
||||
if (viewPager != null && index != -1) {
|
||||
viewPager?.currentItem = index
|
||||
updateBottomBarBadges()
|
||||
}
|
||||
}
|
||||
|
||||
private fun indexForTaskType(taskType: String?): Int {
|
||||
if (taskType != null) {
|
||||
for (index in 0 until (viewFragmentsDictionary?.size ?: 0)) {
|
||||
val fragment = viewFragmentsDictionary?.get(index)
|
||||
if (fragment != null && taskType == fragment.className) {
|
||||
return index
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
override fun getDisplayedClassName(): String? = null
|
||||
|
||||
override fun customTitle(): String? = null
|
||||
|
||||
override fun addToBackStack(): Boolean = false
|
||||
|
||||
companion object {
|
||||
private val TASK_CREATED_RESULT = 1
|
||||
private val TASK_UPDATED_RESULT = 2
|
||||
}
|
||||
}
|
||||
|
|
@ -92,6 +92,7 @@ public abstract class BaseTaskViewHolder extends RecyclerView.ViewHolder impleme
|
|||
|
||||
public void bindHolder(Task newTask, int position) {
|
||||
this.task = newTask;
|
||||
itemView.setBackgroundResource(R.color.white);
|
||||
if (this.canContainMarkdown()) {
|
||||
if (this.task.getParsedText() != null) {
|
||||
this.titleTextView.setText(this.task.getParsedText());
|
||||
|
|
@ -120,7 +121,7 @@ public abstract class BaseTaskViewHolder extends RecyclerView.ViewHolder impleme
|
|||
this.titleTextView.setText(this.task.getText());
|
||||
this.notesTextView.setText(this.task.getNotes());
|
||||
}
|
||||
if (this.task.getNotes() != null && this.task.getNotes().length() > 0) {
|
||||
if (this.task.getNotes().length() > 0) {
|
||||
this.notesTextView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
this.notesTextView.setVisibility(View.GONE);
|
||||
|
|
|
|||
Loading…
Reference in a new issue