diff options
author | Stefan Niedermann <info@niedermann.it> | 2020-05-02 22:16:47 +0300 |
---|---|---|
committer | Stefan Niedermann <info@niedermann.it> | 2020-05-02 22:16:47 +0300 |
commit | b784be03e6f63e9089ee0ac07179bb7f15ffc2a3 (patch) | |
tree | d5fc826dd3aff28856e43a217745e9d0ce06d776 | |
parent | f30dde0702dff5163582e8df4f1ae4cbab28e534 (diff) |
Filter based on tabs
9 files changed, 295 insertions, 126 deletions
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterAssigneesFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterAssigneesFragment.java new file mode 100644 index 000000000..388a0d266 --- /dev/null +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterAssigneesFragment.java @@ -0,0 +1,48 @@ +package it.niedermann.nextcloud.deck.ui.filter; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import it.niedermann.nextcloud.deck.R; +import it.niedermann.nextcloud.deck.databinding.DialogFilterAssigneesBinding; +import it.niedermann.nextcloud.deck.model.internal.FilterInformation; +import it.niedermann.nextcloud.deck.persistence.sync.SyncManager; +import it.niedermann.nextcloud.deck.ui.MainViewModel; + +import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce; +import static it.niedermann.nextcloud.deck.util.DimensionUtil.dpToPx; + +public class FilterAssigneesFragment extends Fragment { + + private FilterInformation filterInformation; + private DialogFilterAssigneesBinding binding; + private MainViewModel mainViewModel; + private UserFilterAdapter userAdapter; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + binding = DialogFilterAssigneesBinding.inflate(requireActivity().getLayoutInflater()); + mainViewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class); + final SyncManager syncManager = new SyncManager(requireActivity()); + + this.filterInformation = mainViewModel.getFilterInformation().getValue(); + if (this.filterInformation == null) { + this.filterInformation = new FilterInformation(); + } + observeOnce(syncManager.findProposalsForUsersToAssign(mainViewModel.getCurrentAccount().getId(), mainViewModel.getCurrentBoardLocalId()), requireActivity(), (users) -> { + userAdapter = new UserFilterAdapter(dpToPx(requireContext(), R.dimen.avatar_size), mainViewModel.getCurrentAccount(), users, this.filterInformation.getUsers()); + binding.users.setNestedScrollingEnabled(false); + binding.users.setAdapter(userAdapter); + }); + return super.onCreateView(inflater, container, savedInstanceState); + } +} diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDialogFragment.java index a912892bd..7388b0bbe 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDialogFragment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDialogFragment.java @@ -2,93 +2,55 @@ package it.niedermann.nextcloud.deck.ui.filter; import android.app.Dialog; import android.os.Bundle; -import android.view.View; -import android.widget.AdapterView; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.lifecycle.Lifecycle; import androidx.lifecycle.ViewModelProvider; +import androidx.viewpager2.adapter.FragmentStateAdapter; + +import com.google.android.material.tabs.TabLayoutMediator; import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.databinding.DialogFilterBinding; -import it.niedermann.nextcloud.deck.model.enums.EDueType; -import it.niedermann.nextcloud.deck.model.internal.FilterInformation; -import it.niedermann.nextcloud.deck.persistence.sync.SyncManager; import it.niedermann.nextcloud.deck.ui.MainViewModel; +import it.niedermann.nextcloud.deck.ui.branding.BrandedActivity; import it.niedermann.nextcloud.deck.ui.branding.BrandedAlertDialogBuilder; import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment; -import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce; -import static it.niedermann.nextcloud.deck.util.DimensionUtil.dpToPx; - public class FilterDialogFragment extends BrandedDialogFragment { private DialogFilterBinding binding; - private MainViewModel viewModel; - private LabelFilterAdapter labelAdapter; - private UserFilterAdapter userAdapter; - private OverdueFilterAdapter overdueAdapter; - private FilterInformation filterInformation; + private MainViewModel mainViewModel; + + private final static int[] tabTitles = new int[]{ + R.string.filter_tags_title, + R.string.filter_assignees_title, + R.string.filter_duedate_title + }; @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - viewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class); - this.filterInformation = viewModel.getFilterInformation().getValue(); - if (this.filterInformation == null) { - this.filterInformation = new FilterInformation(); - } + mainViewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class); final AlertDialog.Builder dialogBuilder = new BrandedAlertDialogBuilder(requireContext()); - final SyncManager syncManager = new SyncManager(requireActivity()); binding = DialogFilterBinding.inflate(requireActivity().getLayoutInflater()); - - overdueAdapter = new OverdueFilterAdapter(requireContext()); - binding.overdue.setAdapter(overdueAdapter); - binding.overdue.setSelection(overdueAdapter.getPosition(this.filterInformation.getDueType())); - binding.overdue.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - filterInformation.setDueType(overdueAdapter.getItem(position)); - } - - @Override - public void onNothingSelected(AdapterView<?> parent) { - filterInformation.setDueType(EDueType.NO_FILTER); - } - }); - - observeOnce(syncManager.findProposalsForLabelsToAssign(viewModel.getCurrentAccount().getId(), viewModel.getCurrentBoardLocalId()), requireActivity(), (labels) -> { - labelAdapter = new LabelFilterAdapter(labels, this.filterInformation.getLabels()); - binding.labels.setNestedScrollingEnabled(false); - binding.labels.setAdapter(labelAdapter); - }); - - observeOnce(syncManager.findProposalsForUsersToAssign(viewModel.getCurrentAccount().getId(), viewModel.getCurrentBoardLocalId()), requireActivity(), (users) -> { - userAdapter = new UserFilterAdapter(dpToPx(requireContext(), R.dimen.avatar_size), viewModel.getCurrentAccount(), users, this.filterInformation.getUsers()); - binding.users.setNestedScrollingEnabled(false); - binding.users.setAdapter(userAdapter); - }); + binding.viewPager.setAdapter(new TabsPagerAdapter(getChildFragmentManager(), getLifecycle())); + new TabLayoutMediator(binding.tabLayout, binding.viewPager, (tab, position) -> tab.setText(tabTitles[position])).attach(); return dialogBuilder .setTitle(R.string.simple_filter) .setView(binding.getRoot()) .setNeutralButton(android.R.string.cancel, null) - .setNegativeButton(R.string.simple_clear, (a, b) -> viewModel.postFilterInformation(null)) - .setPositiveButton(R.string.simple_filter, (a, b) -> { - filterInformation.clearLabels(); - filterInformation.addAllLabels(labelAdapter.getSelected()); - - filterInformation.clearUsers(); - filterInformation.addAllUsers(userAdapter.getSelected()); - - viewModel.postFilterInformation(hasActiveFilter(filterInformation) ? filterInformation : null); - }) + .setNegativeButton(R.string.simple_clear, (a, b) -> mainViewModel.postFilterInformation(null)) + .setPositiveButton(R.string.simple_filter, null) .create(); } @@ -98,16 +60,33 @@ public class FilterDialogFragment extends BrandedDialogFragment { @Override public void applyBrand(int mainColor, int textColor) { - + binding.tabLayout.setSelectedTabIndicatorColor(BrandedActivity.getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor)); } - /** - * @return whether or not the given filterInformation has any actual filters set - */ - private static boolean hasActiveFilter(@Nullable FilterInformation filterInformation) { - if (filterInformation == null) { - return false; + private static class TabsPagerAdapter extends FragmentStateAdapter { + + TabsPagerAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) { + super(fragmentManager, lifecycle); + } + + @NonNull + @Override + public Fragment createFragment(int position) { + switch (position) { + case 0: + return new FilterLabelsFragment(); + case 1: + return new FilterAssigneesFragment(); + case 2: + return new FilterDuedateFragment(); + default: + throw new IllegalArgumentException("position must be between 0 and 2"); + } + } + + @Override + public int getItemCount() { + return tabTitles.length; } - return filterInformation.getDueType() != EDueType.NO_FILTER || filterInformation.getUsers().size() > 0 || filterInformation.getLabels().size() > 0; } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDuedateFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDuedateFragment.java new file mode 100644 index 000000000..54970d1c3 --- /dev/null +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDuedateFragment.java @@ -0,0 +1,51 @@ +package it.niedermann.nextcloud.deck.ui.filter; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import it.niedermann.nextcloud.deck.databinding.DialogFilterDuedateBinding; +import it.niedermann.nextcloud.deck.model.enums.EDueType; +import it.niedermann.nextcloud.deck.model.internal.FilterInformation; +import it.niedermann.nextcloud.deck.ui.MainViewModel; + +public class FilterDuedateFragment extends Fragment { + + private FilterInformation filterInformation; + private DialogFilterDuedateBinding binding; + private MainViewModel mainViewModel; + private OverdueFilterAdapter overdueAdapter; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + binding = DialogFilterDuedateBinding.inflate(requireActivity().getLayoutInflater()); + mainViewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class); + overdueAdapter = new OverdueFilterAdapter(requireContext()); + binding.overdue.setAdapter(overdueAdapter); + this.filterInformation = mainViewModel.getFilterInformation().getValue(); + if (this.filterInformation == null) { + this.filterInformation = new FilterInformation(); + } + binding.overdue.setSelection(overdueAdapter.getPosition(this.filterInformation.getDueType())); + binding.overdue.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + filterInformation.setDueType(overdueAdapter.getItem(position)); + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { + filterInformation.setDueType(EDueType.NO_FILTER); + } + }); + return super.onCreateView(inflater, container, savedInstanceState); + } +} diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterLabelsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterLabelsFragment.java new file mode 100644 index 000000000..bf4b5edbf --- /dev/null +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterLabelsFragment.java @@ -0,0 +1,45 @@ +package it.niedermann.nextcloud.deck.ui.filter; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import it.niedermann.nextcloud.deck.databinding.DialogFilterLabelsBinding; +import it.niedermann.nextcloud.deck.model.internal.FilterInformation; +import it.niedermann.nextcloud.deck.persistence.sync.SyncManager; +import it.niedermann.nextcloud.deck.ui.MainViewModel; + +import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce; + +public class FilterLabelsFragment extends Fragment { + + private FilterInformation filterInformation; + private DialogFilterLabelsBinding binding; + private MainViewModel mainViewModel; + private LabelFilterAdapter labelAdapter; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + binding = DialogFilterLabelsBinding.inflate(requireActivity().getLayoutInflater()); + mainViewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class); + final SyncManager syncManager = new SyncManager(requireActivity()); + + this.filterInformation = mainViewModel.getFilterInformation().getValue(); + if (this.filterInformation == null) { + this.filterInformation = new FilterInformation(); + } + observeOnce(syncManager.findProposalsForLabelsToAssign(mainViewModel.getCurrentAccount().getId(), mainViewModel.getCurrentBoardLocalId()), requireActivity(), (labels) -> { + labelAdapter = new LabelFilterAdapter(labels, this.filterInformation.getLabels()); + binding.labels.setNestedScrollingEnabled(false); + binding.labels.setAdapter(labelAdapter); + }); + return super.onCreateView(inflater, container, savedInstanceState); + } +} diff --git a/app/src/main/res/layout/dialog_filter.xml b/app/src/main/res/layout/dialog_filter.xml index 2ef7716dc..1de6f5bb0 100644 --- a/app/src/main/res/layout/dialog_filter.xml +++ b/app/src/main/res/layout/dialog_filter.xml @@ -1,66 +1,16 @@ <?xml version="1.0" encoding="utf-8"?> -<ScrollView 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" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:orientation="vertical"> - <LinearLayout + <com.google.android.material.tabs.TabLayout + android:id="@+id/tab_layout" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:padding="?attr/dialogPreferredPadding"> + android:layout_height="wrap_content" /> - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/spacer_1x" - android:labelFor="@id/overdue" - android:text="@string/filter_by_tag" - android:textAppearance="?attr/textAppearancePopupMenuHeader" /> - - <androidx.recyclerview.widget.RecyclerView - android:id="@+id/labels" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:choiceMode="multipleChoice" - app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" - tools:itemCount="4" - tools:listitem="@layout/item_filter_label" /> - - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/spacer_3x" - android:layout_marginBottom="@dimen/spacer_1x" - android:labelFor="@id/overdue" - android:text="@string/filter_by_assigned_user" - android:textAppearance="?attr/textAppearancePopupMenuHeader" /> - - <androidx.recyclerview.widget.RecyclerView - android:id="@+id/users" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:choiceMode="multipleChoice" - app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" - tools:itemCount="4" - tools:listitem="@layout/item_filter_user" /> - - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/spacer_3x" - android:layout_marginBottom="@dimen/spacer_1x" - android:labelFor="@id/overdue" - android:text="@string/filter_by_duedate" - android:textAppearance="?attr/textAppearancePopupMenuHeader" /> - - <androidx.appcompat.widget.AppCompatSpinner - android:id="@+id/overdue" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:prompt="@string/simple_overdue" - android:spinnerMode="dropdown" - tools:listitem="@android:layout/simple_list_item_1" /> - </LinearLayout> -</ScrollView>
\ No newline at end of file + <androidx.viewpager2.widget.ViewPager2 + android:id="@+id/view_pager" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/dialog_filter_assignees.xml b/app/src/main/res/layout/dialog_filter_assignees.xml new file mode 100644 index 000000000..2cb0831a0 --- /dev/null +++ b/app/src/main/res/layout/dialog_filter_assignees.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<ScrollView 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:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="?attr/dialogPreferredPadding"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacer_3x" + android:layout_marginBottom="@dimen/spacer_1x" + android:labelFor="@id/overdue" + android:text="@string/filter_by_assigned_user" + android:textAppearance="?attr/textAppearancePopupMenuHeader" /> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/users" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:choiceMode="multipleChoice" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" + tools:itemCount="4" + tools:listitem="@layout/item_filter_user" /> + </LinearLayout> +</ScrollView>
\ No newline at end of file diff --git a/app/src/main/res/layout/dialog_filter_duedate.xml b/app/src/main/res/layout/dialog_filter_duedate.xml new file mode 100644 index 000000000..a59216a72 --- /dev/null +++ b/app/src/main/res/layout/dialog_filter_duedate.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="?attr/dialogPreferredPadding"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacer_3x" + android:layout_marginBottom="@dimen/spacer_1x" + android:labelFor="@id/overdue" + android:text="@string/filter_by_duedate" + android:textAppearance="?attr/textAppearancePopupMenuHeader" /> + + <androidx.appcompat.widget.AppCompatSpinner + android:id="@+id/overdue" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:prompt="@string/simple_overdue" + android:spinnerMode="dropdown" + tools:listitem="@android:layout/simple_list_item_1" /> + </LinearLayout> +</ScrollView>
\ No newline at end of file diff --git a/app/src/main/res/layout/dialog_filter_labels.xml b/app/src/main/res/layout/dialog_filter_labels.xml new file mode 100644 index 000000000..aab612217 --- /dev/null +++ b/app/src/main/res/layout/dialog_filter_labels.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<ScrollView 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:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="?attr/dialogPreferredPadding"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/spacer_1x" + android:labelFor="@id/overdue" + android:text="@string/filter_by_tag" + android:textAppearance="?attr/textAppearancePopupMenuHeader" /> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/labels" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:choiceMode="multipleChoice" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" + tools:itemCount="4" + tools:listitem="@layout/item_filter_label" /> + </LinearLayout> +</ScrollView>
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6258a0ff7..6b7964f3c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -219,4 +219,7 @@ <string name="tag_already_exists">%1$s does already exist</string> <string name="tag_successfully_added">%1$s successfully added</string> <string name="edit_tag">Edit %1$s</string> + <string name="filter_tags_title">Tags</string> + <string name="filter_assignees_title">Assignees</string> + <string name="filter_duedate_title">Due date</string> </resources> |