diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/AbstractCardViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/AbstractCardViewHolder.java index da9790a0d..7653f4ff3 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/AbstractCardViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/AbstractCardViewHolder.java @@ -22,7 +22,6 @@ import org.jetbrains.annotations.Contract; import java.time.Instant; -import java.time.ZoneId; import java.util.List; import java.util.stream.Collectors; @@ -32,10 +31,9 @@ import it.niedermann.nextcloud.deck.model.User; import it.niedermann.nextcloud.deck.model.enums.DBStatus; import it.niedermann.nextcloud.deck.model.full.FullCard; -import it.niedermann.nextcloud.deck.ui.theme.DeckViewThemeUtils; import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils; +import it.niedermann.nextcloud.deck.ui.view.DueDateChip; import it.niedermann.nextcloud.deck.util.AttachmentUtil; -import it.niedermann.nextcloud.deck.util.DateUtil; import it.niedermann.nextcloud.deck.util.MimeTypeUtil; import it.niedermann.nextcloud.sso.glide.SingleSignOnUrl; @@ -91,7 +89,7 @@ public void bind(@NonNull FullCard fullCard, @NonNull Account account, @Nullable }); } - protected abstract TextView getCardDueDate(); + protected abstract DueDateChip getCardDueDate(); protected abstract ImageView getNotSyncedYet(); @@ -113,12 +111,14 @@ public MaterialCardView getDraggable() { return getCard(); } - private static void setupDueDate(@NonNull TextView cardDueDate, @NonNull Card card) { + private static void setupDueDate(@NonNull DueDateChip cardDueDate, @NonNull Card card) { final boolean isDone = card.getDone() != null; final Instant date = isDone ? card.getDone() : card.getDueDate(); - cardDueDate.setText(DateUtil.getRelativeDateTimeString(cardDueDate.getContext(), date.toEpochMilli())); - DeckViewThemeUtils.themeDueDate(cardDueDate, date.atZone(ZoneId.systemDefault()).toLocalDate(), isDone); + if (date == null) { + throw new IllegalArgumentException("Expected due date or done date to be present but both were null."); + } + cardDueDate.setDueDate(date, isDone); } protected static void setupCoverImages(@NonNull Account account, @NonNull ViewGroup coverImagesHolder, @NonNull FullCard fullCard, int maxCoverImagesCount) { diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CompactCardViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CompactCardViewHolder.java index cf947c90b..7c53451a5 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CompactCardViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CompactCardViewHolder.java @@ -19,6 +19,7 @@ import it.niedermann.nextcloud.deck.model.Label; import it.niedermann.nextcloud.deck.model.full.FullCard; import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils; +import it.niedermann.nextcloud.deck.ui.view.DueDateChip; public class CompactCardViewHolder extends AbstractCardViewHolder { private final ItemCardCompactBinding binding; @@ -63,7 +64,7 @@ public MaterialCardView getDraggable() { } @Override - protected TextView getCardDueDate() { + protected DueDateChip getCardDueDate() { return binding.cardDueDate; } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardOnlyTitleViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardOnlyTitleViewHolder.java index 27aacc614..1b6b2b3a0 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardOnlyTitleViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardOnlyTitleViewHolder.java @@ -12,6 +12,7 @@ import com.google.android.material.card.MaterialCardView; import it.niedermann.nextcloud.deck.databinding.ItemCardDefaultOnlyTitleBinding; +import it.niedermann.nextcloud.deck.ui.view.DueDateChip; public class DefaultCardOnlyTitleViewHolder extends AbstractCardViewHolder { private final ItemCardDefaultOnlyTitleBinding binding; @@ -35,7 +36,7 @@ public MaterialCardView getDraggable() { } @Override - protected TextView getCardDueDate() { + protected DueDateChip getCardDueDate() { return binding.cardDueDate; } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardViewHolder.java index dc6e5a956..083480736 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardViewHolder.java @@ -19,6 +19,7 @@ import it.niedermann.nextcloud.deck.model.Account; import it.niedermann.nextcloud.deck.model.full.FullCard; import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils; +import it.niedermann.nextcloud.deck.ui.view.DueDateChip; public class DefaultCardViewHolder extends AbstractCardViewHolder { private final ItemCardDefaultBinding binding; @@ -93,7 +94,7 @@ public void bind(@NonNull FullCard fullCard, @NonNull Account account, @Nullable } @Override - protected TextView getCardDueDate() { + protected DueDateChip getCardDueDate() { return binding.cardDueDate; } 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 d1b1535fd..d52b78f96 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 @@ -2,7 +2,6 @@ import static com.nextcloud.android.common.ui.util.ColorStateListUtilsKt.buildColorStateList; import static com.nextcloud.android.common.ui.util.PlatformThemeUtil.isDarkMode; -import static java.time.temporal.ChronoUnit.DAYS; import android.content.Context; import android.content.res.ColorStateList; @@ -11,7 +10,6 @@ import android.graphics.drawable.StateListDrawable; import android.os.Build; import android.widget.ImageView; -import android.widget.TextView; import androidx.annotation.AttrRes; import androidx.annotation.ColorInt; @@ -23,7 +21,6 @@ import androidx.core.content.ContextCompat; import androidx.core.content.res.ResourcesCompat; import androidx.core.graphics.drawable.DrawableCompat; -import androidx.core.widget.TextViewCompat; import com.google.android.material.search.SearchBar; import com.google.android.material.search.SearchView; @@ -35,7 +32,6 @@ 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.R; @@ -195,39 +191,6 @@ private Optional getStateDrawable(@NonNull StateListDrawable draw return Optional.empty(); } - - @Deprecated(forRemoval = true) - public static void themeDueDate(@NonNull TextView cardDueDate, @NonNull LocalDate date, boolean isDone) { - final var context = cardDueDate.getContext(); - - @ColorInt @Nullable Integer textColor = null; - @DrawableRes int backgroundDrawable = 0; - - if (isDone) { - // due date: done - backgroundDrawable = R.drawable.due_done_background; - textColor = ContextCompat.getColor(context, R.color.due_text_done); - } else { - final long diff = DAYS.between(LocalDate.now(), date); - - if (diff == 0) { - // due date: today - backgroundDrawable = R.drawable.due_today_background; - textColor = ContextCompat.getColor(context, R.color.due_text_today); - } else if (diff < 0) { - // due date: overdue - backgroundDrawable = R.drawable.due_overdue_background; - textColor = ContextCompat.getColor(context, R.color.due_text_overdue); - } // else we use default text styling - } - - cardDueDate.setBackgroundResource(backgroundDrawable); - if (textColor != null) { - cardDueDate.setTextColor(textColor); - TextViewCompat.setCompoundDrawableTintList(cardDueDate, ColorStateList.valueOf(textColor)); - } - } - @Deprecated(forRemoval = true) public static Drawable getTintedImageView(@NonNull Context context, @DrawableRes int imageId, @ColorInt int color) { final var drawable = ContextCompat.getDrawable(context, imageId); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java new file mode 100644 index 000000000..568dfb053 --- /dev/null +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java @@ -0,0 +1,105 @@ +package it.niedermann.nextcloud.deck.ui.view; + +import static java.time.temporal.ChronoUnit.DAYS; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.util.AttributeSet; +import android.util.TypedValue; + +import androidx.annotation.ColorInt; +import androidx.annotation.ColorRes; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.Px; +import androidx.core.content.ContextCompat; + +import com.google.android.material.chip.Chip; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; + +import it.niedermann.android.util.DimensionUtil; +import it.niedermann.nextcloud.deck.R; +import it.niedermann.nextcloud.deck.util.DateUtil; + +public class DueDateChip extends Chip { + + protected @ColorInt int colorOnSurface; + + public DueDateChip(Context context) { + super(context); + initialize(); + } + + public DueDateChip(Context context, AttributeSet attrs) { + super(context, attrs); + initialize(); + } + + public DueDateChip(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(); + } + + private void initialize() { + setEnsureMinTouchTargetSize(false); + setMinHeight(0); + setChipMinHeight(0); + @Px final var padding = DimensionUtil.INSTANCE.dpToPx(getContext(), R.dimen.spacer_1x); + setPadding(padding, padding, padding, padding); + setClickable(false); + + final var typedValue = new TypedValue(); + final var theme = getContext().getTheme(); + theme.resolveAttribute(R.attr.colorOnSurface, typedValue, true); + this.colorOnSurface = typedValue.data; + } + + public void setDueDate(@NonNull Instant date, boolean isDone) { + setText(DateUtil.getRelativeDateTimeString(getContext(), date.toEpochMilli())); + + @DrawableRes final int chipIconRes; + @Nullable @ColorRes final Integer textColorRes; + @ColorRes final int backgroundColorRes; + + if (isDone) { // Done + chipIconRes = R.drawable.ic_check_white_24dp; + backgroundColorRes = R.color.due_done; + textColorRes = R.color.due_text_done; + + } else { + final long diff = DAYS.between(LocalDate.now(), date.atZone(ZoneId.systemDefault()).toLocalDate()); + + if (diff == 0) { // Today + chipIconRes = R.drawable.ic_time_24; + backgroundColorRes = R.color.due_today; + textColorRes = R.color.due_text_today; + + } else if (diff < 0) { // Overdue + chipIconRes = R.drawable.ic_time_filled_24; + backgroundColorRes = R.color.due_overdue; + textColorRes = R.color.due_text_overdue; + + } else { // Future + chipIconRes = R.drawable.ic_time_24; + backgroundColorRes = android.R.color.transparent; + textColorRes = null; + } + } + + setChipIcon(ContextCompat.getDrawable(getContext(), chipIconRes)); + setChipBackgroundColorResource(backgroundColorRes); + + if (textColorRes == null) { + setTextColor(colorOnSurface); + setChipIconTint(ColorStateList.valueOf(colorOnSurface)); + + } else { + setTextColor(ContextCompat.getColor(getContext(), textColorRes)); + setChipIconTintResource(textColorRes); + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/due_done_background.xml b/app/src/main/res/drawable/due_done_background.xml deleted file mode 100644 index cdc93a0b9..000000000 --- a/app/src/main/res/drawable/due_done_background.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/due_overdue_background.xml b/app/src/main/res/drawable/due_overdue_background.xml deleted file mode 100644 index 658797d91..000000000 --- a/app/src/main/res/drawable/due_overdue_background.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/due_today_background.xml b/app/src/main/res/drawable/due_today_background.xml deleted file mode 100644 index fc0a6a727..000000000 --- a/app/src/main/res/drawable/due_today_background.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_time_24.xml b/app/src/main/res/drawable/ic_time_24.xml new file mode 100644 index 000000000..e0355a270 --- /dev/null +++ b/app/src/main/res/drawable/ic_time_24.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/src/main/res/drawable/ic_time_filled_24.xml b/app/src/main/res/drawable/ic_time_filled_24.xml new file mode 100644 index 000000000..77d3da030 --- /dev/null +++ b/app/src/main/res/drawable/ic_time_filled_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/item_card_compact.xml b/app/src/main/res/layout/item_card_compact.xml index 3a14b0d43..16336d4d4 100644 --- a/app/src/main/res/layout/item_card_compact.xml +++ b/app/src/main/res/layout/item_card_compact.xml @@ -52,15 +52,11 @@ app:srcCompat="@drawable/ic_sync_blue_24dp" tools:visibility="visible" /> - - diff --git a/app/src/main/res/layout/item_card_default_only_title.xml b/app/src/main/res/layout/item_card_default_only_title.xml index 1739a2905..145023167 100644 --- a/app/src/main/res/layout/item_card_default_only_title.xml +++ b/app/src/main/res/layout/item_card_default_only_title.xml @@ -37,15 +37,11 @@ app:srcCompat="@drawable/ic_sync_blue_24dp" tools:visibility="visible" /> -