From c48c06cd6155db09ce8b1bd99ef703fc6ec42ef9 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Thu, 9 Mar 2023 14:01:45 +0100 Subject: fix: Reset filter information when switching board Signed-off-by: Stefan Niedermann --- .../ui/accountswitcher/AccountSwitcherDialog.java | 7 +- .../accountswitcher/AccountSwitcherViewHolder.java | 7 +- .../deck/ui/filter/FilterDueTypeAdapter.java | 7 +- .../deck/ui/filter/FilterLabelsAdapter.java | 7 +- .../deck/ui/filter/FilterUserAdapter.java | 7 +- .../nextcloud/deck/ui/main/MainActivity.java | 9 +-- .../ui/manageaccounts/ManageAccountViewHolder.java | 7 +- .../deck/ui/preparecreate/PickStackViewHolder.java | 8 +-- .../ui/preparecreate/PrepareCreateActivity.java | 2 +- .../deck/ui/theme/DeckViewThemeUtils.java | 84 ++++++++++++++++++---- app/src/main/res/drawable/filter.xml | 14 ++++ app/src/main/res/layout/activity_main.xml | 51 ++++--------- 12 files changed, 116 insertions(+), 94 deletions(-) create mode 100644 app/src/main/res/drawable/filter.xml diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherDialog.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherDialog.java index 4a2ef80e6..7dd47213c 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherDialog.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherDialog.java @@ -5,7 +5,6 @@ import static android.app.Activity.RESULT_OK; import android.app.Dialog; import android.content.Intent; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.view.View; @@ -115,9 +114,7 @@ public class AccountSwitcherDialog extends DialogFragment { } private void applyTheme(int color) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - final var utils = ThemeUtils.of(color, requireContext()); - utils.deck.colorSelectedCheck(binding.check.getContext(), binding.check.getDrawable()); - } + final var utils = ThemeUtils.of(color, requireContext()); + utils.deck.themeSelectedCheck(binding.check.getContext(), binding.check.getDrawable()); } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java index 0efa7f769..253e9eb60 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java @@ -1,7 +1,6 @@ package it.niedermann.nextcloud.deck.ui.accountswitcher; import android.net.Uri; -import android.os.Build; import android.text.TextUtils; import android.view.View; @@ -43,9 +42,7 @@ public class AccountSwitcherViewHolder extends RecyclerView.ViewHolder { itemView.setOnClickListener((v) -> onAccountClick.accept(account)); binding.delete.setVisibility(View.GONE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - final var utils = ThemeUtils.of(account.getColor(), itemView.getContext()); - utils.deck.colorSelectedCheck(binding.currentAccountIndicator.getContext(), binding.currentAccountIndicator.getDrawable()); - } + final var utils = ThemeUtils.of(account.getColor(), itemView.getContext()); + utils.deck.themeSelectedCheck(binding.currentAccountIndicator.getContext(), binding.currentAccountIndicator.getDrawable()); } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDueTypeAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDueTypeAdapter.java index 7d218e19e..cf46b392e 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDueTypeAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDueTypeAdapter.java @@ -1,6 +1,5 @@ package it.niedermann.nextcloud.deck.ui.filter; -import android.os.Build; import android.view.LayoutInflater; import android.view.ViewGroup; @@ -90,10 +89,8 @@ public class FilterDueTypeAdapter extends RecyclerView.Adapter= Build.VERSION_CODES.Q) { - final var utils = ThemeUtils.of(color, itemView.getContext()); - utils.deck.colorSelectedCheck(binding.selectedCheck.getContext(), binding.selectedCheck.getDrawable()); - } + final var utils = ThemeUtils.of(color, itemView.getContext()); + utils.deck.themeSelectedCheck(binding.selectedCheck.getContext(), binding.selectedCheck.getDrawable()); } } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterLabelsAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterLabelsAdapter.java index 194540139..0a8dadfa2 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterLabelsAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterLabelsAdapter.java @@ -1,7 +1,6 @@ package it.niedermann.nextcloud.deck.ui.filter; import android.content.res.ColorStateList; -import android.os.Build; import android.view.LayoutInflater; import android.view.ViewGroup; @@ -125,10 +124,8 @@ public class FilterLabelsAdapter extends RecyclerView.Adapter= Build.VERSION_CODES.Q) { - final var utils = ThemeUtils.of(color, itemView.getContext()); - utils.deck.colorSelectedCheck(binding.selectedCheck.getContext(), binding.selectedCheck.getDrawable()); - } + final var utils = ThemeUtils.of(color, itemView.getContext()); + utils.deck.themeSelectedCheck(binding.selectedCheck.getContext(), binding.selectedCheck.getDrawable()); } } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterUserAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterUserAdapter.java index b042954be..9c89a08a9 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterUserAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterUserAdapter.java @@ -1,6 +1,5 @@ package it.niedermann.nextcloud.deck.ui.filter; -import android.os.Build; import android.view.LayoutInflater; import android.view.ViewGroup; @@ -130,10 +129,8 @@ public class FilterUserAdapter extends RecyclerView.Adapter= Build.VERSION_CODES.Q) { - final var utils = ThemeUtils.of(color, itemView.getContext()); - utils.deck.colorSelectedCheck(binding.selectedCheck.getContext(), binding.selectedCheck.getDrawable()); - } + final var utils = ThemeUtils.of(color, itemView.getContext()); + utils.deck.themeSelectedCheck(binding.selectedCheck.getContext(), binding.selectedCheck.getDrawable()); } } } \ No newline at end of file diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/main/MainActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/main/MainActivity.java index b6c3d8a73..644f024bc 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/main/MainActivity.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/main/MainActivity.java @@ -165,7 +165,7 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen stackAdapter = new StackAdapter(this); binding.viewPager.setAdapter(stackAdapter); binding.viewPager.setOffscreenPageLimit(2); - binding.filter.setOnClickListener((v) -> FilterDialogFragment.newInstance().show(getSupportFragmentManager(), EditStackDialogFragment.class.getCanonicalName())); + binding.filterWrapper.setOnClickListener((v) -> FilterDialogFragment.newInstance().show(getSupportFragmentManager(), EditStackDialogFragment.class.getCanonicalName())); binding.filterText.addTextChangedListener(new OnTextChangedWatcher(filterViewModel::setFilterText)); binding.enableSearch.setOnClickListener(v -> showFilterTextToolbar()); binding.toolbar.setOnClickListener(v -> showFilterTextToolbar()); @@ -197,7 +197,7 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen drawerMenuInflater = new DrawerMenuInflater<>(this, binding.navigationView.getMenu()); preferencesViewModel.isDebugModeEnabled$().observe(this, enabled -> headerBinding.copyDebugLogs.setVisibility(enabled ? View.VISIBLE : View.GONE)); - filterViewModel.hasActiveFilter().observe(this, hasActiveFilter -> binding.filterIndicator.setVisibility(hasActiveFilter ? View.VISIBLE : View.GONE)); + filterViewModel.hasActiveFilter().observe(this, hasActiveFilter -> binding.filterWrapper.setActivated(hasActiveFilter)); // Flag to distinguish user initiated stack changes from stack changes derived by changing the board final var boardChanged = new AtomicBoolean(true); @@ -318,7 +318,6 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen private Map applyBoards(@NonNull Account account, boolean hasArchivedBoards, @Nullable List fullBoards) { DeckLog.verbose("=== Apply Boards", fullBoards, "for", account); - filterViewModel.clearFilterInformation(true); binding.navigationView.setItemIconTintList(null); final Map navigationMap; @@ -338,6 +337,8 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen protected void applyBoard(@NonNull Account account, @NonNull Map navigationMap, @Nullable FullBoard currentBoard) { DeckLog.verbose("===== Apply Board", currentBoard); + filterViewModel.clearFilterInformation(true); + if (currentBoard == null) { applyBoardTheme(account.getColor()); showEditButtonsIfPermissionsGranted(false, false); @@ -424,11 +425,11 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen private void applyBoardTheme(@ColorInt int color) { final var utils = ThemeUtils.of(color, this); + utils.deck.themeFilterIndicator(this, binding.filterWrapper.getDrawable()); utils.deck.themeTabLayout(binding.stackTitles); utils.material.themeExtendedFAB(binding.fab); utils.androidx.themeSwipeRefreshLayout(binding.swipeRefreshLayout); utils.platform.colorEditText(binding.filterText); - utils.platform.tintDrawable(this, binding.filterIndicator.getDrawable()); binding.emptyContentViewStacks.applyTheme(color); } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java index 3a3465099..79ba73c32 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java @@ -4,7 +4,6 @@ import static android.view.View.GONE; import static android.view.View.VISIBLE; import android.net.Uri; -import android.os.Build; import android.text.TextUtils; import android.view.View; @@ -58,9 +57,7 @@ public class ManageAccountViewHolder extends RecyclerView.ViewHolder { binding.currentAccountIndicator.setVisibility(GONE); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - final var utils = ThemeUtils.of(account.getColor(), itemView.getContext()); - utils.deck.colorSelectedCheck(binding.currentAccountIndicator.getContext(), binding.currentAccountIndicator.getDrawable()); - } + final var utils = ThemeUtils.of(account.getColor(), itemView.getContext()); + utils.deck.themeSelectedCheck(binding.currentAccountIndicator.getContext(), binding.currentAccountIndicator.getDrawable()); } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PickStackViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PickStackViewHolder.java index 499c55871..dd176d534 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PickStackViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PickStackViewHolder.java @@ -1,7 +1,5 @@ package it.niedermann.nextcloud.deck.ui.preparecreate; -import android.os.Build; - import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -38,9 +36,7 @@ class PickStackViewHolder extends RecyclerView.ViewHolder implements Themed { @Override public void applyTheme(@ColorInt int color) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - final var utils = ThemeUtils.of(color, itemView.getContext()); - utils.deck.colorSelectedCheck(binding.selectedCheck.getContext(), binding.selectedCheck.getDrawable()); - } + final var utils = ThemeUtils.of(color, itemView.getContext()); + utils.deck.themeSelectedCheck(binding.selectedCheck.getContext(), binding.selectedCheck.getDrawable()); } } \ No newline at end of file diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PrepareCreateActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PrepareCreateActivity.java index d34c8ae72..1a87cd2c7 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PrepareCreateActivity.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PrepareCreateActivity.java @@ -39,7 +39,7 @@ public class PrepareCreateActivity extends PickStackActivity { if (requireContent()) { fullCard = viewModel.createFullCard(account.getServerDeckVersionAsObject(), getContent()); } else { - final Intent intent = getIntent(); + final var intent = getIntent(); if (intent == null) { throw new IllegalStateException("Intent should not be null because title is required."); } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeckViewThemeUtils.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeckViewThemeUtils.java index 83a508a75..db0134600 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeckViewThemeUtils.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeckViewThemeUtils.java @@ -12,12 +12,13 @@ import android.os.Build; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.AttrRes; import androidx.annotation.ColorInt; import androidx.annotation.ColorRes; import androidx.annotation.DrawableRes; +import androidx.annotation.IdRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; import androidx.core.content.ContextCompat; import androidx.core.content.res.ResourcesCompat; import androidx.core.graphics.drawable.DrawableCompat; @@ -30,9 +31,10 @@ import com.nextcloud.android.common.ui.theme.utils.AndroidViewThemeUtils; import com.nextcloud.android.common.ui.theme.utils.ColorRole; import com.nextcloud.android.common.ui.theme.utils.MaterialViewThemeUtils; +import java.lang.reflect.InvocationTargetException; import java.time.LocalDate; +import java.util.Optional; -import it.niedermann.nextcloud.deck.DeckLog; import it.niedermann.nextcloud.deck.R; import kotlin.Pair; @@ -73,7 +75,7 @@ public class DeckViewThemeUtils extends ViewThemeUtilsBase { public Drawable themeNavigationViewIcon(@NonNull Context context, @DrawableRes int icon) { return withScheme(context, scheme -> { - final var colorStateListe = buildColorStateList( + final var colorStateList = buildColorStateList( new Pair<>(android.R.attr.state_checked, scheme.getOnSecondaryContainer()), new Pair<>(-android.R.attr.state_checked, scheme.getOnSurfaceVariant()) ); @@ -81,7 +83,7 @@ public class DeckViewThemeUtils extends ViewThemeUtilsBase { final var drawable = ContextCompat.getDrawable(context, icon); assert drawable != null; final var wrapped = DrawableCompat.wrap(drawable).mutate(); - DrawableCompat.setTintList(wrapped, colorStateListe); + DrawableCompat.setTintList(wrapped, colorStateList); wrapped.invalidateSelf(); return wrapped; @@ -101,22 +103,74 @@ public class DeckViewThemeUtils extends ViewThemeUtilsBase { /** * Use only for @drawable/selected_check */ - @RequiresApi(api = Build.VERSION_CODES.Q) - public void colorSelectedCheck(@NonNull Context context, @NonNull Drawable selectedCheck) { + public void themeSelectedCheck(@NonNull Context context, @NonNull Drawable selectedCheck) { + getStateDrawable(selectedCheck, android.R.attr.state_selected, R.id.foreground) + .ifPresent(drawable -> platform.tintDrawable(context, drawable, ColorRole.ON_PRIMARY)); + getStateDrawable(selectedCheck, android.R.attr.state_selected, R.id.background) + .ifPresent(drawable -> platform.tintDrawable(context, drawable, ColorRole.PRIMARY)); + } + + /** + * Use only for @drawable/filter + */ + public void themeFilterIndicator(@NonNull Context context, @NonNull Drawable filter) { + getStateDrawable(filter, android.R.attr.state_activated, R.id.indicator) + .ifPresent(drawable -> platform.tintDrawable(context, drawable, ColorRole.PRIMARY)); + } + + private Optional getStateDrawable(@NonNull Drawable drawable, @AttrRes int state, @IdRes int layerId) { + return getStateDrawable(drawable, new int[]{state}, layerId); + } + + private Optional getStateDrawable(@NonNull Drawable drawable, @AttrRes int[] states, @IdRes int layerId) { try { - final var check = ((StateListDrawable) selectedCheck); - final var checkSelectedIndex = check.findStateDrawableIndex(new int[]{android.R.attr.state_selected}); - final var checkSelectedDrawable = check.getStateDrawable(checkSelectedIndex); - - final var backgroundDrawable = ((LayerDrawable) checkSelectedDrawable).findDrawableByLayerId(R.id.background); - final var foregroundDrawable = ((LayerDrawable) checkSelectedDrawable).findDrawableByLayerId(R.id.foreground); - platform.tintDrawable(context, backgroundDrawable, ColorRole.PRIMARY); - platform.tintDrawable(context, foregroundDrawable, ColorRole.ON_PRIMARY); + final var stateListDrawable = ((StateListDrawable) drawable); + return findStateDrawableIndex(stateListDrawable, states) + .flatMap(stateIndex -> getStateDrawable(stateListDrawable, stateIndex)) + .map(layerDrawable -> layerDrawable.findDrawableByLayerId(layerId)); } catch (Exception e) { - DeckLog.error(e); + return Optional.empty(); + } + } + + private Optional findStateDrawableIndex(@NonNull StateListDrawable drawable, int[] states) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return Optional.of(drawable.findStateDrawableIndex(states)); + } else { + try { + // getStateDrawableIndex has been renamed and made public since API 29 / Android 10 / Android Q + + //noinspection JavaReflectionMemberAccess + final var getStateDrawableIndex = StateListDrawable.class.getMethod("getStateDrawableIndex", int[].class); + //noinspection PrimitiveArrayArgumentToVarargsMethod + return Optional.ofNullable((Integer) getStateDrawableIndex.invoke(drawable, states)); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + return Optional.empty(); + } } } + private Optional getStateDrawable(@NonNull StateListDrawable drawable, int index) { + Drawable result; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + result = drawable.getStateDrawable(index); + } else { + try { + result = (Drawable) StateListDrawable.class.getMethod("getStateDrawable", int.class).invoke(drawable, index); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + return Optional.empty(); + } + } + + if (result instanceof LayerDrawable) { + return Optional.of((LayerDrawable) result); + } + + return Optional.empty(); + } + + @Deprecated(forRemoval = true) public static void themeDueDate(@NonNull TextView cardDueDate, @NonNull LocalDate dueDate) { final var context = cardDueDate.getContext(); diff --git a/app/src/main/res/drawable/filter.xml b/app/src/main/res/drawable/filter.xml new file mode 100644 index 000000000..a3933e864 --- /dev/null +++ b/app/src/main/res/drawable/filter.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 81cdd33ca..28915cd29 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -144,7 +144,6 @@ android:id="@+id/enableSearch" android:layout_width="wrap_content" android:layout_height="0dp" - android:layout_gravity="center_vertical|end" android:background="@null" android:contentDescription="@string/simple_search" android:paddingHorizontal="@dimen/spacer_1hx" @@ -156,52 +155,27 @@ app:tint="?attr/colorAccent" tools:targetApi="o" /> - - - - - - + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/filter" + app:tint="?attr/colorAccent" /> - -- cgit v1.2.3