From 8471bf3b4dea916ed87f70c6b497bb18336723e3 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 14 Jan 2024 11:18:03 +0100 Subject: feat(done): Enhance due date / done UX in board view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use ✔️ icon when done is present in favor of 📆 / 🕙 in board view - Change icon from 📆 to 🕙 for due dates - Move temporal information into own reusable component to encapsulate logic Refs: #1556 Signed-off-by: Stefan Niedermann --- .../nextcloud/deck/ui/view/DueDateChip.java | 105 +++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java (limited to 'app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java') 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 -- cgit v1.2.3 From b8d1a2a2a90df0c7f08de51076d9f6c3a1015f67 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 16 Jan 2024 07:58:11 +0100 Subject: chore(done): Support compact mode Refs: #1556 Signed-off-by: Stefan Niedermann --- .../nextcloud/deck/ui/view/DueDateChip.java | 36 ++++++++++++++-------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java') 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 index 568dfb053..88b86daf3 100644 --- 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 @@ -27,24 +27,30 @@ import it.niedermann.nextcloud.deck.util.DateUtil; public class DueDateChip extends Chip { - protected @ColorInt int colorOnSurface; + @ColorInt + protected final int colorOnSurface; + protected final boolean compactMode; public DueDateChip(Context context) { - super(context); - initialize(); + this(context, null); } public DueDateChip(Context context, AttributeSet attrs) { - super(context, attrs); - initialize(); + this(context, attrs, R.attr.chipStyle); } public DueDateChip(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - initialize(); - } - private void initialize() { + final var typedValue = new TypedValue(); + final var theme = getContext().getTheme(); + theme.resolveAttribute(R.attr.colorOnSurface, typedValue, true); + this.colorOnSurface = typedValue.data; + + final var styles = context.obtainStyledAttributes(attrs, R.styleable.DueDateChip, defStyleAttr, 0); + this.compactMode = styles.getBoolean(R.styleable.DueDateChip_compactMode, false); + styles.recycle(); + setEnsureMinTouchTargetSize(false); setMinHeight(0); setChipMinHeight(0); @@ -52,14 +58,18 @@ public class DueDateChip extends Chip { 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; + if (compactMode) { + setChipEndPadding(0); + setTextEndPadding(0); + } } public void setDueDate(@NonNull Instant date, boolean isDone) { - setText(DateUtil.getRelativeDateTimeString(getContext(), date.toEpochMilli())); + if (compactMode) { + setText(null); + } else { + setText(DateUtil.getRelativeDateTimeString(getContext(), date.toEpochMilli())); + } @DrawableRes final int chipIconRes; @Nullable @ColorRes final Integer textColorRes; -- cgit v1.2.3 From b66c01dcf779bc57edb161da036989c40e765d07 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 16 Jan 2024 08:04:17 +0100 Subject: chore(done): Adjust due date chip to match Deck server app - Make done icon circular - Adjust logic to determine colors Refs: #1556 Signed-off-by: Stefan Niedermann --- .../nextcloud/deck/ui/view/DueDateChip.java | 45 ++++++++++------------ 1 file changed, 21 insertions(+), 24 deletions(-) (limited to 'app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java') 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 index 88b86daf3..952c5105f 100644 --- 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 @@ -1,6 +1,6 @@ package it.niedermann.nextcloud.deck.ui.view; -import static java.time.temporal.ChronoUnit.DAYS; +import static java.time.temporal.ChronoUnit.HOURS; import android.content.Context; import android.content.res.ColorStateList; @@ -18,7 +18,7 @@ import androidx.core.content.ContextCompat; import com.google.android.material.chip.Chip; import java.time.Instant; -import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.ZoneId; import it.niedermann.android.util.DimensionUtil; @@ -52,11 +52,12 @@ public class DueDateChip extends Chip { styles.recycle(); setEnsureMinTouchTargetSize(false); - setMinHeight(0); - setChipMinHeight(0); + setClickable(false); + @Px final var padding = DimensionUtil.INSTANCE.dpToPx(getContext(), R.dimen.spacer_1x); setPadding(padding, padding, padding, padding); - setClickable(false); + setMinHeight(0); + setChipMinHeight(0); if (compactMode) { setChipEndPadding(0); @@ -76,28 +77,24 @@ public class DueDateChip extends Chip { @ColorRes final int backgroundColorRes; if (isDone) { // Done - chipIconRes = R.drawable.ic_check_white_24dp; + chipIconRes = R.drawable.ic_check_circle_24; 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; - } + } else if (date.isBefore(Instant.now())) { // Overdue + chipIconRes = R.drawable.ic_time_filled_24; + backgroundColorRes = R.color.due_overdue; + textColorRes = R.color.due_text_overdue; + + } else if (HOURS.between(LocalDateTime.now(), date.atZone(ZoneId.systemDefault())) < 24) { // Next 24 Hours + chipIconRes = R.drawable.ic_time_24; + backgroundColorRes = R.color.due_today; + textColorRes = R.color.due_text_today; + + } else { // Future + chipIconRes = R.drawable.ic_time_24; + backgroundColorRes = android.R.color.transparent; + textColorRes = null; } setChipIcon(ContextCompat.getDrawable(getContext(), chipIconRes)); -- cgit v1.2.3 From 976308dd0f67af6d3af704df1d7b218c95f044c8 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 16 Jan 2024 09:35:41 +0100 Subject: chore(done): Use onSurfaceVariant for future due dates Signed-off-by: Stefan Niedermann --- app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java') 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 index 952c5105f..8a1d547e0 100644 --- 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 @@ -44,7 +44,7 @@ public class DueDateChip extends Chip { final var typedValue = new TypedValue(); final var theme = getContext().getTheme(); - theme.resolveAttribute(R.attr.colorOnSurface, typedValue, true); + theme.resolveAttribute(R.attr.colorOnSurfaceVariant, typedValue, true); this.colorOnSurface = typedValue.data; final var styles = context.obtainStyledAttributes(attrs, R.styleable.DueDateChip, defStyleAttr, 0); -- cgit v1.2.3 From 1d18d0b078ae795692a58ec3c8abf0c430030be2 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Wed, 17 Jan 2024 10:59:53 +0100 Subject: chore(deps): Do no longer rely on android-commons lib to calculate dp to px Signed-off-by: Stefan Niedermann --- .../main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java') 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 index 8a1d547e0..095a46bd3 100644 --- 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 @@ -21,7 +21,6 @@ import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; -import it.niedermann.android.util.DimensionUtil; import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.util.DateUtil; @@ -54,7 +53,7 @@ public class DueDateChip extends Chip { setEnsureMinTouchTargetSize(false); setClickable(false); - @Px final var padding = DimensionUtil.INSTANCE.dpToPx(getContext(), R.dimen.spacer_1x); + @Px final var padding = getResources().getDimensionPixelSize(R.dimen.spacer_1x); setPadding(padding, padding, padding, padding); setMinHeight(0); setChipMinHeight(0); -- cgit v1.2.3