Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stefan-niedermann/nextcloud-deck.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/it/niedermann/nextcloud/deck/ui/card')
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/AbstractCardViewHolder.java24
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CompactCardViewHolder.java5
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardOnlyTitleViewHolder.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardViewHolder.java20
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/UserAutoCompleteAdapter.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsBottomsheetBehaviorCallback.java12
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsMentionProposer.java5
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/ItemCommentViewHolder.java5
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/AssigneeViewHolder.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java165
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDueDateView.java302
13 files changed, 393 insertions, 163 deletions
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 697b21e1e..193fc7a2c 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
@@ -21,7 +21,7 @@ import com.nextcloud.android.common.ui.theme.utils.ColorRole;
import org.jetbrains.annotations.Contract;
-import java.time.ZoneId;
+import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;
@@ -31,10 +31,9 @@ import it.niedermann.nextcloud.deck.model.Card;
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;
@@ -59,13 +58,15 @@ public abstract class AbstractCardViewHolder extends RecyclerView.ViewHolder {
if (utils != null) {
utils.platform.colorImageView(getNotSyncedYet(), ColorRole.PRIMARY);
+ utils.platform.colorImageView(getCardMenu(), ColorRole.ON_SURFACE);
+ utils.platform.colorTextView(getCardTitle(), ColorRole.ON_SURFACE);
}
// TODO should be discussed with UX
// utils.material.themeCardView(getCard());
getNotSyncedYet().setVisibility(DBStatus.LOCAL_EDITED.equals(fullCard.getStatusEnum()) ? View.VISIBLE : View.GONE);
- if (fullCard.getCard().getDueDate() != null) {
+ if (fullCard.getCard().getDueDate() != null || fullCard.getCard().getDone() != null) {
setupDueDate(getCardDueDate(), fullCard.getCard());
getCardDueDate().setVisibility(View.VISIBLE);
} else {
@@ -90,13 +91,13 @@ public abstract class AbstractCardViewHolder extends RecyclerView.ViewHolder {
});
}
- protected abstract TextView getCardDueDate();
+ protected abstract DueDateChip getCardDueDate();
protected abstract ImageView getNotSyncedYet();
protected abstract TextView getCardTitle();
- protected abstract View getCardMenu();
+ protected abstract ImageView getCardMenu();
protected abstract MaterialCardView getCard();
@@ -112,9 +113,14 @@ public abstract class AbstractCardViewHolder extends RecyclerView.ViewHolder {
return getCard();
}
- private static void setupDueDate(@NonNull TextView cardDueDate, @NonNull Card card) {
- cardDueDate.setText(DateUtil.getRelativeDateTimeString(cardDueDate.getContext(), card.getDueDate().toEpochMilli()));
- DeckViewThemeUtils.themeDueDate(cardDueDate, card.getDueDate().atZone(ZoneId.systemDefault()).toLocalDate());
+ private static void setupDueDate(@NonNull DueDateChip cardDueDate, @NonNull Card card) {
+ final boolean isDone = card.getDone() != null;
+ final Instant date = isDone ? card.getDone() : card.getDueDate();
+
+ 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..8dc4a3e48 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.Account;
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 class CompactCardViewHolder extends AbstractCardViewHolder {
}
@Override
- protected TextView getCardDueDate() {
+ protected DueDateChip getCardDueDate() {
return binding.cardDueDate;
}
@@ -78,7 +79,7 @@ public class CompactCardViewHolder extends AbstractCardViewHolder {
}
@Override
- protected View getCardMenu() {
+ protected ImageView getCardMenu() {
return binding.cardMenu;
}
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..4e16f8127 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
@@ -1,6 +1,5 @@
package it.niedermann.nextcloud.deck.ui.card;
-import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.ImageView;
@@ -12,6 +11,7 @@ import androidx.annotation.Nullable;
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 +35,7 @@ public class DefaultCardOnlyTitleViewHolder extends AbstractCardViewHolder {
}
@Override
- protected TextView getCardDueDate() {
+ protected DueDateChip getCardDueDate() {
return binding.cardDueDate;
}
@@ -50,7 +50,7 @@ public class DefaultCardOnlyTitleViewHolder extends AbstractCardViewHolder {
}
@Override
- protected View getCardMenu() {
+ protected ImageView getCardMenu() {
return binding.cardMenu;
}
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..20ce6dd1d 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
@@ -13,12 +13,16 @@ import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.google.android.material.card.MaterialCardView;
+import com.nextcloud.android.common.ui.theme.utils.ColorRole;
+
+import java.util.stream.Stream;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ItemCardDefaultBinding;
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;
@@ -78,7 +82,7 @@ public class DefaultCardViewHolder extends AbstractCardViewHolder {
final var taskStatus = fullCard.getCard().getTaskStatus();
if (taskStatus.taskCount > 0) {
binding.cardCountTasks.setText(context.getResources().getString(R.string.task_count, String.valueOf(taskStatus.doneCount), String.valueOf(taskStatus.taskCount)));
- binding.cardCountTasks.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(context, R.drawable.ic_check_grey600_24dp), null, null, null);
+ binding.cardCountTasks.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(context, R.drawable.ic_check_box_24), null, null, null);
binding.cardCountTasks.setVisibility(View.VISIBLE);
} else {
final String description = fullCard.getCard().getDescription();
@@ -90,10 +94,20 @@ public class DefaultCardViewHolder extends AbstractCardViewHolder {
binding.cardCountTasks.setVisibility(View.GONE);
}
}
+
+ if (utils != null) {
+ Stream.of(
+ binding.cardCountAttachments,
+ binding.cardCountTasks,
+ binding.cardCountComments
+ ).forEach(v -> {
+ utils.platform.colorTextView(v, ColorRole.ON_SURFACE_VARIANT );
+ });
+ }
}
@Override
- protected TextView getCardDueDate() {
+ protected DueDateChip getCardDueDate() {
return binding.cardDueDate;
}
@@ -108,7 +122,7 @@ public class DefaultCardViewHolder extends AbstractCardViewHolder {
}
@Override
- protected View getCardMenu() {
+ protected ImageView getCardMenu() {
return binding.cardMenu;
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/UserAutoCompleteAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/UserAutoCompleteAdapter.java
index 286c95018..9140e305e 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/UserAutoCompleteAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/UserAutoCompleteAdapter.java
@@ -15,7 +15,6 @@ import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundExce
import java.util.List;
import it.niedermann.android.reactivelivedata.ReactiveLiveData;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ItemAutocompleteUserBinding;
@@ -82,7 +81,7 @@ public class UserAutoCompleteAdapter extends AutoCompleteAdapter<User> {
}
Glide.with(binding.icon.getContext())
- .load(account.getAvatarUrl(DimensionUtil.INSTANCE.dpToPx(binding.icon.getContext(), R.dimen.avatar_size), getItem(position).getUid()))
+ .load(account.getAvatarUrl(binding.icon.getResources().getDimensionPixelSize(R.dimen.avatar_size), getItem(position).getUid()))
.apply(RequestOptions.circleCropTransform())
.placeholder(R.drawable.ic_person_grey600_24dp)
.error(R.drawable.ic_person_grey600_24dp)
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsBottomsheetBehaviorCallback.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsBottomsheetBehaviorCallback.java
index 6b60bbffd..473937753 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsBottomsheetBehaviorCallback.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsBottomsheetBehaviorCallback.java
@@ -1,5 +1,9 @@
package it.niedermann.nextcloud.deck.ui.card.attachments;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN;
+
import android.content.Context;
import android.view.View;
@@ -16,12 +20,6 @@ import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import it.niedermann.android.util.DimensionUtil;
-
-import static android.view.View.GONE;
-import static android.view.View.VISIBLE;
-import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN;
-
public class CardAttachmentsBottomsheetBehaviorCallback extends BottomSheetBehavior.BottomSheetCallback {
@NonNull
private final OnBackPressedCallback backPressedCallback;
@@ -55,7 +53,7 @@ public class CardAttachmentsBottomsheetBehaviorCallback extends BottomSheetBehav
this.bottomNavigation = bottomNavigation;
this.backdropColorExpanded = ContextCompat.getColor(context, backdropColorExpanded);
this.backdropColorCollapsed = ContextCompat.getColor(context, backdropColorCollapsed);
- this.bottomNavigationHeight = DimensionUtil.INSTANCE.dpToPx(context, bottomNavigationHeight);
+ this.bottomNavigationHeight = context.getResources().getDimensionPixelSize(bottomNavigationHeight);
}
@Override
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java
index f5f0606fa..4de403ba7 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java
@@ -62,7 +62,6 @@ import id.zelory.compressor.constraint.QualityConstraint;
import id.zelory.compressor.constraint.ResolutionConstraint;
import id.zelory.compressor.constraint.SizeConstraint;
import it.niedermann.android.reactivelivedata.ReactiveLiveData;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.FragmentCardEditTabAttachmentsBinding;
@@ -156,7 +155,7 @@ public class CardAttachmentsFragment extends Fragment implements AttachmentDelet
this.binding.attachmentsList.setVisibility(VISIBLE);
}
});
- galleryItemDecoration = new GalleryItemDecoration(DimensionUtil.INSTANCE.dpToPx(requireContext(), R.dimen.spacer_1qx));
+ galleryItemDecoration = new GalleryItemDecoration(getResources().getDimensionPixelSize(R.dimen.spacer_1qx));
mBottomSheetBehaviour = BottomSheetBehavior.from(binding.bottomSheetParent);
mBottomSheetBehaviour.setDraggable(true);
mBottomSheetBehaviour.setHideable(true);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java
index e6739e3ee..caa13cb07 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java
@@ -25,7 +25,6 @@ import com.nextcloud.android.sso.api.EmptyResponse;
import java.time.Instant;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.FragmentCardEditTabCommentsBinding;
@@ -95,7 +94,7 @@ public class CardCommentsFragment extends Fragment implements Themed, CommentEdi
binding.comments.setAdapter(adapter);
binding.replyCommentCancelButton.setOnClickListener((v) -> commentsViewModel.setReplyToComment(null));
Glide.with(binding.avatar.getContext())
- .load(editCardViewModel.getAccount().getAvatarUrl(DimensionUtil.INSTANCE.dpToPx(binding.avatar.getContext(), R.dimen.icon_size_details)))
+ .load(editCardViewModel.getAccount().getAvatarUrl(binding.avatar.getResources().getDimensionPixelSize(R.dimen.icon_size_details)))
.apply(RequestOptions.circleCropTransform())
.placeholder(R.drawable.ic_person_grey600_24dp)
.error(R.drawable.ic_person_grey600_24dp)
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsMentionProposer.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsMentionProposer.java
index 403e26886..fe10f6cfa 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsMentionProposer.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsMentionProposer.java
@@ -19,7 +19,6 @@ import java.util.ArrayList;
import java.util.List;
import it.niedermann.android.reactivelivedata.ReactiveLiveData;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.User;
@@ -56,9 +55,9 @@ public class CardCommentsMentionProposer implements TextWatcher {
this.mentionProposerWrapper = mentionProposerWrapper;
this.mentionProposer = avatarProposer;
baseRepository = new BaseRepository(editText.getContext());
- avatarSize = DimensionUtil.INSTANCE.dpToPx(mentionProposer.getContext(), R.dimen.avatar_size_small);
+ avatarSize = mentionProposer.getResources().getDimensionPixelSize(R.dimen.avatar_size_small);
layoutParams = new LinearLayout.LayoutParams(avatarSize, avatarSize);
- layoutParams.setMarginEnd(DimensionUtil.INSTANCE.dpToPx(mentionProposer.getContext(), R.dimen.spacer_1x));
+ layoutParams.setMarginEnd(mentionProposer.getResources().getDimensionPixelSize(R.dimen.spacer_1x));
}
@Override
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/ItemCommentViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/ItemCommentViewHolder.java
index 221beea76..7a4df435f 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/ItemCommentViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/ItemCommentViewHolder.java
@@ -21,7 +21,6 @@ import java.util.HashMap;
import java.util.function.Consumer;
import it.niedermann.android.util.ClipboardUtil;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ItemCommentBinding;
import it.niedermann.nextcloud.deck.model.Account;
@@ -43,7 +42,7 @@ public class ItemCommentViewHolder extends RecyclerView.ViewHolder {
public void bind(@NonNull FullDeckComment comment, @NonNull Account account, @Nullable ThemeUtils utils, @NonNull MenuInflater inflater, @NonNull CommentDeletedListener deletedListener, @NonNull CommentSelectAsReplyListener selectAsReplyListener, @NonNull FragmentManager fragmentManager, @NonNull Consumer<CharSequence> editListener) {
Glide.with(binding.avatar.getContext())
- .load(account.getAvatarUrl(DimensionUtil.INSTANCE.dpToPx(binding.avatar.getContext(), R.dimen.avatar_size), comment.getComment().getActorId()))
+ .load(account.getAvatarUrl(binding.avatar.getResources().getDimensionPixelSize(R.dimen.avatar_size), comment.getComment().getActorId()))
.apply(RequestOptions.circleCropTransform())
.placeholder(R.drawable.ic_person_grey600_24dp)
.error(R.drawable.ic_person_grey600_24dp)
@@ -64,7 +63,7 @@ public class ItemCommentViewHolder extends RecyclerView.ViewHolder {
inflater.inflate(R.menu.comment_menu, menu);
menu.findItem(android.R.id.copy).setOnMenuItemClickListener(item -> ClipboardUtil.INSTANCE.copyToClipboard(itemView.getContext(), comment.getComment().getMessage()));
final var replyMenuItem = menu.findItem(R.id.reply);
- if (comment.getStatusEnum() != DBStatus.LOCAL_EDITED && account.getServerDeckVersionAsObject().supportsCommentsReplys()) {
+ if (comment.getStatusEnum() != DBStatus.LOCAL_EDITED && account.getServerDeckVersionAsObject().supportsCommentsReplies()) {
replyMenuItem.setOnMenuItemClickListener(item -> {
selectAsReplyListener.onSelectAsReply(comment);
return true;
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/AssigneeViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/AssigneeViewHolder.java
index 989b17ef7..8148ff783 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/AssigneeViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/AssigneeViewHolder.java
@@ -8,7 +8,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ItemAssigneeBinding;
import it.niedermann.nextcloud.deck.model.Account;
@@ -25,7 +24,7 @@ public class AssigneeViewHolder extends RecyclerView.ViewHolder {
public void bind(@NonNull Account account, @NonNull User user, @Nullable Consumer<User> onClickListener) {
Glide.with(binding.avatar.getContext())
- .load(account.getAvatarUrl(DimensionUtil.INSTANCE.dpToPx(binding.avatar.getContext(), R.dimen.avatar_size), user.getUid()))
+ .load(account.getAvatarUrl(binding.avatar.getResources().getDimensionPixelSize(R.dimen.avatar_size), user.getUid()))
.apply(RequestOptions.circleCropTransform())
.placeholder(R.drawable.ic_person_grey600_24dp)
.error(R.drawable.ic_person_grey600_24dp)
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java
index 76c99abe9..d86f9361a 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java
@@ -27,23 +27,14 @@ import androidx.recyclerview.widget.GridLayoutManager;
import com.google.android.material.chip.Chip;
import com.google.android.material.snackbar.Snackbar;
+import com.nextcloud.android.common.ui.theme.utils.ColorRole;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
-import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
-import com.wdullaer.materialdatetimepicker.date.DatePickerDialog.OnDateSetListener;
-import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
-import com.wdullaer.materialdatetimepicker.time.TimePickerDialog.OnTimeSetListener;
-
-import java.time.LocalDate;
-import java.time.LocalTime;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.format.FormatStyle;
+
+import java.time.Instant;
import java.util.stream.Stream;
import it.niedermann.android.markdown.MarkdownEditor;
import it.niedermann.android.util.ColorUtil;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.FragmentCardEditTabDetailsBinding;
@@ -59,17 +50,13 @@ import it.niedermann.nextcloud.deck.ui.card.assignee.CardAssigneeDialog;
import it.niedermann.nextcloud.deck.ui.card.assignee.CardAssigneeListener;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
-import it.niedermann.nextcloud.deck.ui.theme.ThemedDatePickerDialog;
import it.niedermann.nextcloud.deck.ui.theme.ThemedSnackbar;
-import it.niedermann.nextcloud.deck.ui.theme.ThemedTimePickerDialog;
-public class CardDetailsFragment extends Fragment implements OnDateSetListener, OnTimeSetListener, CardAssigneeListener {
+public class CardDetailsFragment extends Fragment implements CardDueDateView.DueDateChangedListener, CardAssigneeListener {
private FragmentCardEditTabDetailsBinding binding;
private EditCardViewModel viewModel;
private AssigneeAdapter adapter;
- private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
- private final DateTimeFormatter timeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
private static final String KEY_ACCOUNT = "account";
public static Fragment newInstance(@NonNull Account account) {
@@ -102,9 +89,9 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
return binding.getRoot();
}
- @Px final int avatarSize = DimensionUtil.INSTANCE.dpToPx(requireContext(), R.dimen.avatar_size);
+ @Px final int avatarSize = getResources().getDimensionPixelSize(R.dimen.avatar_size);
final var avatarLayoutParams = new LinearLayout.LayoutParams(avatarSize, avatarSize);
- avatarLayoutParams.setMargins(0, 0, DimensionUtil.INSTANCE.dpToPx(requireContext(), R.dimen.spacer_1x), 0);
+ avatarLayoutParams.setMargins(0, 0, getResources().getDimensionPixelSize(R.dimen.spacer_1x), 0);
setupAssignees();
setupLabels((Account) args.getSerializable(KEY_ACCOUNT));
@@ -121,16 +108,16 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
viewModel.getBoardColor().observe(getViewLifecycleOwner(), this::applyTheme);
}
- @Override
- public void onResume() {
- super.onResume();
-
- // https://github.com/wdullaer/MaterialDateTimePicker#why-are-my-callbacks-lost-when-the-device-changes-orientation
- final var dpd = (DatePickerDialog) getChildFragmentManager().findFragmentByTag(ThemedDatePickerDialog.class.getCanonicalName());
- final var tpd = (TimePickerDialog) getChildFragmentManager().findFragmentByTag(ThemedTimePickerDialog.class.getCanonicalName());
- if (tpd != null) tpd.setOnTimeSetListener(this);
- if (dpd != null) dpd.setOnDateSetListener(this);
- }
+// @Override
+// public void onResume() {
+// super.onResume();
+//
+// // https://github.com/wdullaer/MaterialDateTimePicker#why-are-my-callbacks-lost-when-the-device-changes-orientation
+// final var dpd = (DatePickerDialog) getChildFragmentManager().findFragmentByTag(ThemedDatePickerDialog.class.getCanonicalName());
+// final var tpd = (TimePickerDialog) getChildFragmentManager().findFragmentByTag(ThemedTimePickerDialog.class.getCanonicalName());
+// if (tpd != null) tpd.setOnTimeSetListener(this);
+// if (dpd != null) dpd.setOnDateSetListener(this);
+// }
@Override
public void onDestroy() {
@@ -143,12 +130,13 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
Stream.of(
binding.labelsWrapper,
- binding.dueDateDateWrapper,
- binding.dueDateTimeWrapper,
binding.peopleWrapper,
binding.descriptionEditorWrapper
).forEach(utils.material::colorTextInputLayout);
+ utils.platform.colorImageView(binding.descriptionToggle, ColorRole.SECONDARY);
+
+ binding.cardDueDateView.applyTheme(color);
binding.descriptionEditor.setSearchColor(color);
binding.descriptionViewer.setSearchColor(color);
@@ -194,53 +182,27 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
}
private void setupDueDate() {
- if (this.viewModel.getFullCard().getCard().getDueDate() != null) {
- final var dueDate = this.viewModel.getFullCard().getCard().getDueDate().atZone(ZoneId.systemDefault());
- binding.dueDateDate.setText(dueDate == null ? null : dueDate.format(dateFormatter));
- binding.dueDateTime.setText(dueDate == null ? null : dueDate.format(timeFormatter));
- binding.clearDueDate.setVisibility(VISIBLE);
- } else {
- binding.clearDueDate.setVisibility(GONE);
- binding.dueDateDate.setText(null);
- binding.dueDateTime.setText(null);
- }
-
- if (viewModel.canEdit()) {
- binding.dueDateDate.setOnClickListener(v -> {
- final LocalDate date;
- if (viewModel.getFullCard() != null && viewModel.getFullCard().getCard() != null && viewModel.getFullCard().getCard().getDueDate() != null) {
- date = viewModel.getFullCard().getCard().getDueDate().atZone(ZoneId.systemDefault()).toLocalDate();
- } else {
- date = LocalDate.now();
- }
- viewModel.getCurrentBoardColor(viewModel.getAccount().getId(), viewModel.getBoardId())
- .thenAcceptAsync(color -> ThemedDatePickerDialog.newInstance(this, date.getYear(), date.getMonthValue(), date.getDayOfMonth(), color)
- .show(getChildFragmentManager(), ThemedDatePickerDialog.class.getCanonicalName()), ContextCompat.getMainExecutor(requireContext()));
- });
+ final var version = this.viewModel.getAccount().getServerDeckVersionAsObject();
+ final var card = this.viewModel.getFullCard().getCard();
+ binding.cardDueDateView.setDueDateListener(this);
+ binding.cardDueDateView.setEnabled(this.viewModel.canEdit());
+ binding.cardDueDateView.setDueDate(getChildFragmentManager(), version, card.getDueDate(), card.getDone());
+ }
- binding.dueDateTime.setOnClickListener(v -> {
- final LocalTime time;
- if (viewModel.getFullCard() != null && viewModel.getFullCard().getCard() != null && viewModel.getFullCard().getCard().getDueDate() != null) {
- time = viewModel.getFullCard().getCard().getDueDate().atZone(ZoneId.systemDefault()).toLocalTime();
- } else {
- time = LocalTime.now();
- }
- viewModel.getCurrentBoardColor(viewModel.getAccount().getId(), viewModel.getBoardId())
- .thenAcceptAsync(color -> ThemedTimePickerDialog.newInstance(this, time.getHour(), time.getMinute(), true, color)
- .show(getChildFragmentManager(), ThemedTimePickerDialog.class.getCanonicalName()), ContextCompat.getMainExecutor(requireContext()));
- });
+ @Override
+ public void onDueDateChanged(@Nullable Instant dueDate) {
+ final var version = this.viewModel.getAccount().getServerDeckVersionAsObject();
+ final var card = this.viewModel.getFullCard().getCard();
+ card.setDueDate(dueDate);
+ binding.cardDueDateView.setDueDate(getChildFragmentManager(), version, card.getDueDate(), card.getDone());
+ }
- binding.clearDueDate.setOnClickListener(v -> {
- binding.dueDateDate.setText(null);
- binding.dueDateTime.setText(null);
- viewModel.getFullCard().getCard().setDueDate(null);
- binding.clearDueDate.setVisibility(GONE);
- });
- } else {
- binding.dueDateDate.setEnabled(false);
- binding.dueDateTime.setEnabled(false);
- binding.clearDueDate.setVisibility(GONE);
- }
+ @Override
+ public void onDoneChanged(@Nullable Instant done) {
+ final var version = this.viewModel.getAccount().getServerDeckVersionAsObject();
+ final var card = this.viewModel.getFullCard().getCard();
+ card.setDone(done);
+ binding.cardDueDateView.setDueDate(getChildFragmentManager(), version, card.getDueDate(), card.getDone());
}
private void setupLabels(@NonNull Account account) {
@@ -333,8 +295,8 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
adapter = new AssigneeAdapter((user) -> CardAssigneeDialog.newInstance(user).show(getChildFragmentManager(), CardAssigneeDialog.class.getSimpleName()), viewModel.getAccount());
binding.assignees.setAdapter(adapter);
binding.assignees.post(() -> {
- @Px final int gutter = DimensionUtil.INSTANCE.dpToPx(requireContext(), R.dimen.spacer_1x);
- final int spanCount = (int) (float) binding.labelsWrapper.getWidth() / (DimensionUtil.INSTANCE.dpToPx(requireContext(), R.dimen.avatar_size) + gutter);
+ @Px final int gutter = getResources().getDimensionPixelSize(R.dimen.spacer_1x);
+ final int spanCount = (int) (float) binding.labelsWrapper.getWidth() / (getResources().getDimensionPixelSize(R.dimen.avatar_size) + gutter);
binding.assignees.setLayoutManager(new GridLayoutManager(getContext(), spanCount));
binding.assignees.addItemDecoration(new AssigneeDecoration(spanCount, gutter));
});
@@ -364,53 +326,6 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
}
}
- @Override
- public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
- int hourOfDay;
- int minute;
-
- final var selectedTime = binding.dueDateTime.getText();
- if (TextUtils.isEmpty(selectedTime)) {
- hourOfDay = 0;
- minute = 0;
- } else {
- final LocalTime oldTime = LocalTime.from(this.viewModel.getFullCard().getCard().getDueDate().atZone(ZoneId.systemDefault()));
- hourOfDay = oldTime.getHour();
- minute = oldTime.getMinute();
- }
-
- final var newDateTime = ZonedDateTime.of(
- LocalDate.of(year, monthOfYear + 1, dayOfMonth),
- LocalTime.of(hourOfDay, minute),
- ZoneId.systemDefault()
- );
- this.viewModel.getFullCard().getCard().setDueDate(newDateTime.toInstant());
- binding.dueDateDate.setText(newDateTime.format(dateFormatter));
-
- if (this.viewModel.getFullCard().getCard().getDueDate() == null || this.viewModel.getFullCard().getCard().getDueDate().toEpochMilli() == 0) {
- binding.clearDueDate.setVisibility(GONE);
- } else {
- binding.clearDueDate.setVisibility(VISIBLE);
- }
- }
-
- @Override
- public void onTimeSet(TimePickerDialog view, int hourOfDay, int minute, int second) {
- final var oldInstant = this.viewModel.getFullCard().getCard().getDueDate();
- final var oldDateTime = oldInstant == null ? ZonedDateTime.now() : oldInstant.atZone(ZoneId.systemDefault());
- final var newDateTime = oldDateTime.with(
- LocalTime.of(hourOfDay, minute)
- );
-
- this.viewModel.getFullCard().getCard().setDueDate(newDateTime.toInstant());
- binding.dueDateTime.setText(newDateTime.format(timeFormatter));
- if (this.viewModel.getFullCard().getCard().getDueDate() == null || this.viewModel.getFullCard().getCard().getDueDate().toEpochMilli() == 0) {
- binding.clearDueDate.setVisibility(GONE);
- } else {
- binding.clearDueDate.setVisibility(VISIBLE);
- }
- }
-
private void setupProjects() {
if (viewModel.getFullCard().getProjects().size() > 0) {
binding.projectsTitle.setVisibility(VISIBLE);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDueDateView.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDueDateView.java
new file mode 100644
index 000000000..2266e6c7d
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDueDateView.java
@@ -0,0 +1,302 @@
+package it.niedermann.nextcloud.deck.ui.card.details;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentManager;
+
+import com.nextcloud.android.common.ui.theme.utils.ColorRole;
+import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
+import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
+
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.stream.Stream;
+
+import it.niedermann.nextcloud.deck.R;
+import it.niedermann.nextcloud.deck.databinding.ViewCardDueDateBinding;
+import it.niedermann.nextcloud.deck.model.ocs.Version;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.Themed;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedDatePickerDialog;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedTimePickerDialog;
+
+public class CardDueDateView extends FrameLayout implements DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener, Themed {
+
+ private final ViewCardDueDateBinding binding;
+ @Nullable
+ private DueDateChangedListener dueDateChangedListener;
+ private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("d. MMM yyyy HH:mm");
+ private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
+ private final DateTimeFormatter timeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
+ boolean supportsDone = false;
+ @Nullable
+ private Instant dueDate = null;
+ @Nullable
+ private Instant done = null;
+ @Nullable
+ @ColorInt
+ private Integer color = null;
+ private FragmentManager fragmentManager = null;
+
+ public CardDueDateView(Context context) {
+ super(context);
+ binding = ViewCardDueDateBinding.inflate(LayoutInflater.from(context), this, true);
+ }
+
+ public CardDueDateView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ binding = ViewCardDueDateBinding.inflate(LayoutInflater.from(context), this, true);
+ }
+
+ public CardDueDateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ binding = ViewCardDueDateBinding.inflate(LayoutInflater.from(context), this, true);
+ }
+
+ /**
+ * @noinspection unused
+ */
+ public CardDueDateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ binding = ViewCardDueDateBinding.inflate(LayoutInflater.from(context), this, true);
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ if (enabled != isEnabled()) {
+ super.setEnabled(enabled);
+ render();
+ }
+ }
+
+ public void setDueDate(@NonNull FragmentManager fragmentManager, @NonNull Version version, @Nullable Instant dueDate, @Nullable Instant done) {
+ this.fragmentManager = fragmentManager;
+ this.supportsDone = version.supportsDone();
+ this.dueDate = dueDate;
+ this.done = done;
+ render();
+ }
+
+ private void render() {
+ setVisibilityState();
+ setTextState();
+ setInteraction();
+ }
+
+ private void setVisibilityState() {
+ if (done == null) {
+ Stream.of(
+ binding.dueDateDateWrapper,
+ binding.dueDateTimeWrapper
+ ).forEach(v -> v.setVisibility(View.VISIBLE));
+
+ Stream.of(
+ binding.doneCheck,
+ binding.doneDueDate,
+ binding.doneDate,
+ binding.clearDone
+ ).forEach(v -> v.setVisibility(View.GONE));
+
+ binding.markAsDone.setVisibility(supportsDone ? View.VISIBLE : View.GONE);
+ binding.clearDueDate.setVisibility(dueDate == null || !isEnabled() ? View.GONE : View.VISIBLE);
+ } else {
+
+ Stream.of(
+ binding.doneCheck,
+ binding.doneDate
+ ).forEach(v -> v.setVisibility(View.VISIBLE));
+
+ Stream.of(
+ binding.markAsDone,
+ binding.dueDateDateWrapper,
+ binding.dueDateTimeWrapper,
+ binding.clearDueDate
+ ).forEach(v -> v.setVisibility(View.GONE));
+
+ binding.clearDone.setVisibility(supportsDone ? View.VISIBLE : View.GONE);
+ binding.doneDueDate.setVisibility(dueDate == null || !isEnabled() ? View.GONE : View.VISIBLE);
+ }
+ }
+
+ private void setTextState() {
+ if (done == null) {
+ binding.doneDate.setText(null);
+ binding.doneDueDate.setText(null);
+
+ if (this.dueDate == null) {
+ binding.dueDateDate.setText(null);
+ binding.dueDateTime.setText(null);
+
+ } else {
+ final var dueDate = this.dueDate.atZone(ZoneId.systemDefault());
+ binding.dueDateDate.setText(dueDate.format(dateFormatter));
+ binding.dueDateTime.setText(dueDate.format(timeFormatter));
+ }
+
+ } else {
+ binding.dueDateDate.setText(null);
+ binding.dueDateTime.setText(null);
+
+ binding.doneDate.setText(done.atZone(ZoneId.systemDefault()).format(dateTimeFormatter));
+
+ if (this.dueDate == null) {
+ binding.doneDueDate.setText(null);
+
+ } else {
+ final var dueDate = this.dueDate.atZone(ZoneId.systemDefault());
+ binding.doneDueDate.setText(getContext().getString(R.string.label_due_at, dueDate.format(dateTimeFormatter)));
+ }
+ }
+ }
+
+ private void setInteraction() {
+ final var enabled = isEnabled();
+
+ binding.dueDateDate.setEnabled(enabled);
+ binding.dueDateTime.setEnabled(enabled);
+
+ if (enabled) {
+ binding.clearDone.setOnClickListener(v -> {
+ if (this.dueDateChangedListener != null) {
+ this.dueDateChangedListener.onDoneChanged(null);
+ }
+ });
+
+ if (supportsDone) {
+ binding.markAsDone.setOnClickListener(v -> {
+ if (this.dueDateChangedListener != null) {
+ this.dueDateChangedListener.onDoneChanged(Instant.now());
+ }
+ });
+ } else {
+ binding.markAsDone.setOnClickListener(null);
+ }
+
+ binding.clearDueDate.setOnClickListener(v -> {
+ if (this.dueDateChangedListener != null) {
+ this.dueDateChangedListener.onDueDateChanged(null);
+ }
+ });
+
+ binding.dueDateDate.setOnClickListener(v -> {
+ if (this.fragmentManager == null || this.color == null) {
+ return;
+ }
+ final LocalDate date;
+ if (this.dueDate != null) {
+ date = this.dueDate.atZone(ZoneId.systemDefault()).toLocalDate();
+ } else {
+ date = LocalDate.now();
+ }
+
+ ThemedDatePickerDialog.newInstance(this, date.getYear(), date.getMonthValue(), date.getDayOfMonth(), this.color)
+ .show(this.fragmentManager, ThemedDatePickerDialog.class.getCanonicalName());
+ });
+
+ binding.dueDateTime.setOnClickListener(v -> {
+ if (this.fragmentManager == null || this.color == null) {
+ return;
+ }
+ final LocalTime time;
+ if (this.dueDate != null) {
+ time = this.dueDate.atZone(ZoneId.systemDefault()).toLocalTime();
+ } else {
+ time = LocalTime.now();
+ }
+ ThemedTimePickerDialog.newInstance(this, time.getHour(), time.getMinute(), true, this.color)
+ .show(this.fragmentManager, ThemedTimePickerDialog.class.getCanonicalName());
+ });
+ } else {
+ Stream.of(
+ binding.clearDone,
+ binding.markAsDone,
+ binding.clearDueDate,
+ binding.dueDateDate,
+ binding.dueDateTime
+ ).forEach(v -> v.setOnClickListener(null));
+ }
+ }
+
+ @Override
+ public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
+ int hourOfDay;
+ int minute;
+
+ final var selectedTime = binding.dueDateTime.getText();
+ if (TextUtils.isEmpty(selectedTime)) {
+ hourOfDay = 0;
+ minute = 0;
+ } else {
+ assert this.dueDate != null; // Since selectedTime is not empty and is derived from dueDate, dueDate itself shouldn't be null here.
+ final var oldTime = LocalTime.from(this.dueDate.atZone(ZoneId.systemDefault()));
+ hourOfDay = oldTime.getHour();
+ minute = oldTime.getMinute();
+ }
+
+ final var newDateTime = ZonedDateTime.of(
+ LocalDate.of(year, monthOfYear + 1, dayOfMonth),
+ LocalTime.of(hourOfDay, minute),
+ ZoneId.systemDefault()
+ );
+ this.dueDate = newDateTime.toInstant();
+
+ if (dueDateChangedListener != null) {
+ dueDateChangedListener.onDueDateChanged(newDateTime.toInstant());
+ }
+ }
+
+ @Override
+ public void onTimeSet(TimePickerDialog view, int hourOfDay, int minute, int second) {
+ final var oldDateTime = this.dueDate == null ? ZonedDateTime.now() : this.dueDate.atZone(ZoneId.systemDefault());
+ final var newDateTime = oldDateTime.with(
+ LocalTime.of(hourOfDay, minute)
+ );
+
+ if (dueDateChangedListener != null) {
+ dueDateChangedListener.onDueDateChanged(newDateTime.toInstant());
+ }
+ }
+
+ @Override
+ public void applyTheme(int color) {
+ this.color = color;
+ final var utils = ThemeUtils.of(color, getContext());
+
+ Stream.of(
+ binding.dueDateDateWrapper,
+ binding.dueDateTimeWrapper
+ ).forEach(utils.material::colorTextInputLayout);
+
+ Stream.of(
+ binding.clearDone,
+ binding.clearDueDate
+ ).forEach(v -> utils.platform.colorImageView(v, ColorRole.SECONDARY));
+
+ utils.platform.colorTextView(binding.doneDate, ColorRole.ON_SURFACE);
+ utils.platform.colorTextView(binding.doneDueDate, ColorRole.ON_SURFACE_VARIANT);
+ utils.material.colorMaterialButtonPrimaryTonal(binding.markAsDone);
+ }
+
+ public void setDueDateListener(@Nullable DueDateChangedListener dueDateChangedListener) {
+ this.dueDateChangedListener = dueDateChangedListener;
+ }
+
+ public interface DueDateChangedListener {
+ void onDueDateChanged(@Nullable Instant dueDate);
+
+ void onDoneChanged(@Nullable Instant done);
+ }
+}