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:
authorNiedermann IT-Dienstleistungen <stefan-niedermann@users.noreply.github.com>2024-01-20 00:01:24 +0300
committerGitHub <noreply@github.com>2024-01-20 00:01:24 +0300
commit00eeee817ca231d22c7787e67b6ddd7ae04fdf28 (patch)
treee434ca03b3f1fac903624172638dc7484883fae1
parentb8ee8530fe796f3d13db41429f6a140c55dc22b8 (diff)
parent3ae26363d56157a0869dd6717ce6e069a4a8cc44 (diff)
Merge pull request #1565 from stefan-niedermann/master
Merge master
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md55
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml105
-rw-r--r--.github/ISSUE_TEMPLATE/feature_request.md29
-rw-r--r--.github/ISSUE_TEMPLATE/feature_request.yml45
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/database/DataBaseAdapter.java39
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/database/DeckDatabase.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/database/dao/CardDao.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/database/migration/Migration_32_33.java25
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/model/Card.java14
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/model/enums/EDoneType.java40
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/model/internal/FilterInformation.java15
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/model/ocs/Version.java41
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/model/propagation/CardUpdate.java1
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/remote/api/JsonToEntityParser.java1
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherDialog.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlAdapter.java5
-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
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDialogFragment.java9
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDoneTypeAdapter.java96
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDoneTypeFragment.java47
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterUserAdapter.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterViewModel.java7
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/main/search/SearchCardViewHolder.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/AccountAdapter.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeckViewThemeUtils.java34
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedDatePickerDialog.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedTimePickerDialog.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsUtil.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/view/ColorChooser.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java111
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/view/OverlappingAvatars.java11
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/view/labelchip/CompactLabelChip.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/view/labellayout/LabelLayout.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SingleCardWidget.java28
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/upcoming/UpcomingWidgetFactory.java7
-rw-r--r--app/src/main/res/animator/appbar_elevation_off.xml9
-rw-r--r--app/src/main/res/animator/appbar_elevation_on.xml11
-rw-r--r--app/src/main/res/drawable-hdpi/ic_splash_screen.pngbin1235 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_splash_screen.pngbin827 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_splash_screen.pngbin2542 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_splash_screen.pngbin4045 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_splash_screen.pngbin4276 -> 0 bytes
-rw-r--r--app/src/main/res/drawable/bottom_sheet_rounded.xml9
-rw-r--r--app/src/main/res/drawable/circle.xml8
-rw-r--r--app/src/main/res/drawable/due_overdue_background.xml7
-rw-r--r--app/src/main/res/drawable/due_today_background.xml7
-rw-r--r--app/src/main/res/drawable/due_tomorrow_background.xml7
-rw-r--r--app/src/main/res/drawable/ic_check_box_24.xml5
-rw-r--r--app/src/main/res/drawable/ic_check_circle_24.xml5
-rw-r--r--app/src/main/res/drawable/ic_format_paint_grey600_24dp.xml5
-rw-r--r--app/src/main/res/drawable/ic_time_24.xml6
-rw-r--r--app/src/main/res/drawable/ic_time_filled_24.xml5
-rw-r--r--app/src/main/res/drawable/splash_screen.xml12
-rw-r--r--app/src/main/res/layout/dialog_filter.xml2
-rw-r--r--app/src/main/res/layout/dialog_filter_done.xml10
-rw-r--r--app/src/main/res/layout/fragment_card_edit_tab_details.xml73
-rw-r--r--app/src/main/res/layout/item_card_compact.xml9
-rw-r--r--app/src/main/res/layout/item_card_default.xml11
-rw-r--r--app/src/main/res/layout/item_card_default_only_title.xml8
-rw-r--r--app/src/main/res/layout/item_filter_donetype.xml29
-rw-r--r--app/src/main/res/layout/view_card_due_date.xml143
-rw-r--r--app/src/main/res/layout/widget_single_card.xml2
-rw-r--r--app/src/main/res/menu/archived_card_menu.xml13
-rw-r--r--app/src/main/res/values-ar/strings.xml1
-rw-r--r--app/src/main/res/values-b+en+001/strings.xml1
-rw-r--r--app/src/main/res/values-de/strings.xml1
-rw-r--r--app/src/main/res/values-es/strings.xml1
-rw-r--r--app/src/main/res/values-it/strings.xml7
-rw-r--r--app/src/main/res/values-nb-rNO/strings.xml1
-rw-r--r--app/src/main/res/values-night/colors.xml12
-rw-r--r--app/src/main/res/values-sr/strings.xml1
-rw-r--r--app/src/main/res/values-sv/strings.xml1
-rw-r--r--app/src/main/res/values-zh-rHK/strings.xml1
-rw-r--r--app/src/main/res/values-zh-rTW/strings.xml1
-rw-r--r--app/src/main/res/values/attrs.xml3
-rw-r--r--app/src/main/res/values/colors.xml12
-rw-r--r--app/src/main/res/values/strings.xml33
91 files changed, 1279 insertions, 562 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 51005cef6..000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,55 +0,0 @@
----
-name: 🐞 Bug report
-about: Help us improving by reporting a bug
-labels: bug
----
-
-<!--
-Guidelines for submitting bug reports:
-
-* Bug reports which do not fill the complete issue template will be closed.
-* Please have a look at our [FAQ](https://github.com/stefan-niedermann/nextcloud-deck/blob/master/FAQ.md)
-* Please search the existing issues first, it's likely that your issue was already reported or even fixed.
-* This repository is *only* for issues within the Nextcloud Deck Android app
--->
-Please use **[GitHub reactions](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/)** 👍 to show that you are affected by the same issue. Please don't comment if you have no relevant information to add!
-
-**Describe the bug**
-<!-- A clear and concise description of what the bug is. -->
-
-
-Steps to reproduce the behavior:
-1. Go to '…'
-2. Click on '…'
-3. Scroll down to '…'
-4. See error
-
-
-**Expected behavior**
-<!-- A clear and concise description of what you expected to happen. -->
-
-
-**Screenshots**
-<!-- If applicable, add screenshots to help explain your problem. -->
-
-
-**Versions**
-<!-- "latest" is NOT a version. Depending on your Nextcloud instance the latest versions can vary. -->
- - Nextcloud:
- - Nextcloud Deck:
- - Nextcloud Android:
- - Nextcloud Android Deck:
-
-
-**Smartphone (please complete the following information):**
-- Device:
-- Android-Version:
-- App-Store:
- - [ ] Google Play Store
- - [ ] Google Play Store (Beta channel)
- - [ ] F-Droid
- - [ ] Huawei AppGallery
-
-
-**Stacktrace**
-
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 000000000..d89f71c34
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,105 @@
+name: "🐞 Bug report"
+description: "Help us improving by reporting a bug"
+labels: [ "bug" ]
+body:
+ - type: markdown
+ attributes:
+ value: Please note this is a free and open-source project. All people take on their own time to help you, so please, be patient.
+
+ - type: checkboxes
+ id: before-posting
+ attributes:
+ label: "This issue respects the following points:"
+ description: All conditions are **required**. Your issue can be closed if these are checked incorrectly.
+ options:
+ - label: I have read the [FAQ](https://github.com/stefan-niedermann/nextcloud-deck/blob/master/FAQ.md)
+ required: true
+ - label: I have searched for existing issues
+ required: true
+ - label: The issue affects the Deck Android app, neither the [Deck server app](https://github.com/nextcloud/deck/issues/) nor the [Nextcloud Android app](https://github.com/nextcloud/android/issues).
+ required: true
+
+ - type: textarea
+ id: problem-description
+ attributes:
+ label: Describe the bug
+ description: A clear and concise description of what the bug is. Please add clear steps to reliably reproduce the issue.
+ placeholder: |
+ 1. Go to '…'
+ 2. Click on '…'
+ 3. Scroll down to '…'
+ 4. See error
+ validations:
+ required: true
+
+ - type: textarea
+ id: expected-behavior
+ attributes:
+ label: Expected behavior
+ description: A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem.
+
+ - type: input
+ id: version-nextcloud-android-deck
+ attributes:
+ label: Deck Android version
+ placeholder: Version of this app
+ validations:
+ required: true
+
+ - type: input
+ id: version-nextcloud-deck
+ attributes:
+ label: Deck server version
+ placeholder: Deck Server app version
+ validations:
+ required: true
+
+ - type: input
+ id: version-nextcloud-android
+ attributes:
+ label: Nextcloud Android version
+ placeholder: Nextcloud Android app
+ validations:
+ required: true
+
+ - type: input
+ id: version-nextcloud
+ attributes:
+ label: Nextcloud version
+ placeholder: Your Nextcloud instance
+ validations:
+ required: true
+
+ - type: input
+ id: device
+ attributes:
+ label: Device
+ description: Manufacturer and model
+ placeholder: Samsung Galaxy S24
+ validations:
+ required: true
+
+ - type: input
+ id: android-version
+ attributes:
+ label: Android Version
+ description: Neither MIUI nor One UI or other proprietary manufacturer OS versions
+ placeholder: "14"
+ validations:
+ required: true
+
+ - type: checkboxes
+ id: versions
+ attributes:
+ label: App Store
+ options:
+ - label: Google Play Store
+ - label: Google Play Store (Beta channel)
+ - label: F-Droid
+ - label: Huawei App Gallery
+
+ - type: textarea
+ id: stacktrace
+ attributes:
+ label: Stacktrace
+ description: Copy the error message using the <kbd>Copy</kbd> button. Please do not post a screenshot of the error message.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index 39f47140e..000000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-name: 🚀 Feature request
-about: Suggest an idea for this project
-labels: enhancement
----
-
-<!--
-Guidelines for submitting issues:
-
-* Please search the existing issues first, it's likely that your issue was already reported or even fixed.
-* This repository is *only* for issues within the Nextcloud Deck Android app
--->
-Please use **[GitHub reactions](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/)** 👍 to show that you are affected by the same issue. Please don't comment if you have no relevant information to add!
-
-**Is your feature request related to a problem? Please describe.**
-<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
-
-
-**Describe the solution you'd like**
-<!-- A clear and concise description of what you want to happen. -->
-
-
-**Describe alternatives you've considered**
-<!-- A clear and concise description of any alternative solutions or features you've considered. -->
-
-
-**Additional context**
-<!-- Add any other context or screenshots about the feature request here. -->
-
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 000000000..7ae3788cd
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,45 @@
+name: "🚀 Feature request"
+description: "Propose an idea for Deck Android"
+labels: [ "enhancement" ]
+body:
+
+ - type: markdown
+ attributes:
+ value: |
+ **Guidelines for submitting issues:**
+
+ * Please search the existing issues first, it's likely that your issue was already reported or even fixed.
+ * This repository is *only* for issues within the Deck Android app, **not** for the [Deck server app](https://github.com/nextcloud/deck/issues/) and **not** for the [Nextcloud Android app](https://github.com/nextcloud/android/issues).
+
+ - type: textarea
+ id: problem-description
+ attributes:
+ label: Is your feature request related to a problem? Please describe.
+ description: |
+ A clear and concise description of what the problem is.
+ placeholder: I'm always frustrated when…
+ validations:
+ required: true
+
+ - type: textarea
+ id: preferred-solution
+ attributes:
+ label: Describe the solution you'd like
+ description: |
+ A clear and concise description of what you want to happen.
+ validations:
+ required: true
+
+ - type: textarea
+ id: alternatives
+ attributes:
+ label: Describe alternatives you've considered
+ description: |
+ A clear and concise description of any alternative solutions or features you've considered.
+
+ - type: textarea
+ id: context
+ attributes:
+ label: Additional context
+ description: |
+ Add any other context or screenshots about the feature request here. \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/database/DataBaseAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/database/DataBaseAdapter.java
index 5d3b28950..a95ab7a8c 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/database/DataBaseAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/database/DataBaseAdapter.java
@@ -60,6 +60,7 @@ import it.niedermann.nextcloud.deck.model.Stack;
import it.niedermann.nextcloud.deck.model.User;
import it.niedermann.nextcloud.deck.model.appwidgets.StackWidgetModel;
import it.niedermann.nextcloud.deck.model.enums.DBStatus;
+import it.niedermann.nextcloud.deck.model.enums.EDoneType;
import it.niedermann.nextcloud.deck.model.enums.EDueType;
import it.niedermann.nextcloud.deck.model.full.FullBoard;
import it.niedermann.nextcloud.deck.model.full.FullCard;
@@ -259,9 +260,9 @@ public class DataBaseAdapter {
public LiveData<List<FullCard>> getFullCardsForStack(long accountId, long localStackId, @Nullable FilterInformation filter) {
return new ReactiveLiveData<>(
- filter == null
- ? db.getCardDao().getFullCardsForStack(accountId, localStackId)
- : db.getCardDao().getFilteredFullCardsForStack(getQueryForFilter(filter, accountId, localStackId)))
+ FilterInformation.hasActiveFilter(filter)
+ ? db.getCardDao().getFilteredFullCardsForStack(getQueryForFilter(filter, accountId, localStackId))
+ : db.getCardDao().getFullCardsForStack(accountId, localStackId))
.tap(this::filterRelationsForCard, executor)
.distinctUntilChanged();
@@ -284,9 +285,9 @@ public class DataBaseAdapter {
@WorkerThread
public List<FullCard> getFullCardsForStackDirectly(long accountId, long localStackId, @Nullable FilterInformation filter) {
- return filter == null
- ? db.getCardDao().getFullCardsForStackDirectly(accountId, localStackId)
- : db.getCardDao().getFilteredFullCardsForStackDirectly(getQueryForFilter(filter, accountId, localStackId));
+ return FilterInformation.hasActiveFilter(filter)
+ ? db.getCardDao().getFilteredFullCardsForStackDirectly(getQueryForFilter(filter, accountId, localStackId))
+ : db.getCardDao().getFullCardsForStackDirectly(accountId, localStackId);
}
@AnyThread
@@ -351,24 +352,38 @@ public class DataBaseAdapter {
if (filter.getDueType() != EDueType.NO_FILTER) {
switch (filter.getDueType()) {
case NO_DUE:
- query.append("and c.dueDate is null");
+ query.append("and c.dueDate is null ");
break;
case OVERDUE:
- query.append("and datetime(c.duedate/1000, 'unixepoch', 'localtime') <= datetime('now', 'localtime')");
+ query.append("and datetime(c.duedate/1000, 'unixepoch', 'localtime') <= datetime('now', 'localtime') ");
break;
case TODAY:
- query.append("and datetime(c.duedate/1000, 'unixepoch', 'localtime') between datetime('now', 'localtime') and datetime('now', '+24 hour', 'localtime')");
+ query.append("and datetime(c.duedate/1000, 'unixepoch', 'localtime') between datetime('now', 'localtime') and datetime('now', '+24 hour', 'localtime') ");
break;
case WEEK:
- query.append("and datetime(c.duedate/1000, 'unixepoch', 'localtime') between datetime('now', 'localtime') and datetime('now', '+7 day', 'localtime')");
+ query.append("and datetime(c.duedate/1000, 'unixepoch', 'localtime') between datetime('now', 'localtime') and datetime('now', '+7 day', 'localtime') ");
break;
case MONTH:
- query.append("and datetime(c.duedate/1000, 'unixepoch', 'localtime') between datetime('now', 'localtime') and datetime('now', '+30 day', 'localtime')");
+ query.append("and datetime(c.duedate/1000, 'unixepoch', 'localtime') between datetime('now', 'localtime') and datetime('now', '+30 day', 'localtime') ");
break;
default:
- throw new IllegalArgumentException("You need to add your new EDueType value\"" + filter.getDueType() + "\" here!");
+ throw new IllegalArgumentException("You need to add your new " + EDueType.class.getSimpleName() + " value\"" + filter.getDueType() + "\" here!");
}
}
+
+ if (filter.getDoneType() != EDoneType.NO_FILTER) {
+ switch (filter.getDoneType()) {
+ case DONE:
+ query.append("and (c.done is not null and c.done != 0) ");
+ break;
+ case UNDONE:
+ query.append("and (c.done is null or c.done = 0) ");
+ break;
+ default:
+ throw new IllegalArgumentException("You need to add your new " + EDoneType.class.getSimpleName() + " value\"" + filter.getDueType() + "\" here!");
+ }
+ }
+
if (!TextUtils.isEmpty(filter.getFilterText())) {
query.append(" and (c.description like ? or c.title like ?) ");
String filterText = "%" + filter.getFilterText() + "%";
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/database/DeckDatabase.java b/app/src/main/java/it/niedermann/nextcloud/deck/database/DeckDatabase.java
index b71abece1..a41379e8d 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/database/DeckDatabase.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/database/DeckDatabase.java
@@ -65,6 +65,7 @@ import it.niedermann.nextcloud.deck.database.migration.Migration_28_29;
import it.niedermann.nextcloud.deck.database.migration.Migration_29_30;
import it.niedermann.nextcloud.deck.database.migration.Migration_30_31;
import it.niedermann.nextcloud.deck.database.migration.Migration_31_32;
+import it.niedermann.nextcloud.deck.database.migration.Migration_32_33;
import it.niedermann.nextcloud.deck.database.migration.Migration_8_9;
import it.niedermann.nextcloud.deck.database.migration.Migration_9_10;
import it.niedermann.nextcloud.deck.model.AccessControl;
@@ -135,7 +136,7 @@ import it.niedermann.nextcloud.deck.remote.api.LastSyncUtil;
FilterWidgetSort.class,
},
exportSchema = false,
- version = 32
+ version = 33
)
@TypeConverters({DateTypeConverter.class, EnumConverter.class})
public abstract class DeckDatabase extends RoomDatabase {
@@ -188,6 +189,7 @@ public abstract class DeckDatabase extends RoomDatabase {
.addMigrations(new Migration_29_30(context))
.addMigrations(new Migration_30_31())
.addMigrations(new Migration_31_32(context))
+ .addMigrations(new Migration_32_33())
.fallbackToDestructiveMigration()
.addCallback(ON_CREATE_CALLBACK)
.build();
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/database/dao/CardDao.java b/app/src/main/java/it/niedermann/nextcloud/deck/database/dao/CardDao.java
index 5d25f943f..0f067381e 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/database/dao/CardDao.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/database/dao/CardDao.java
@@ -23,7 +23,8 @@ public interface CardDao extends GenericDao<Card> {
"and (c.deletedAt is null or c.deletedAt = 0) " +
"and (s.deletedAt is null or s.deletedAt = 0) " +
"and (b.deletedAt is null or b.deletedAt = 0) " +
- // FUll Logic: (hasDueDate AND isIn_PRIVATE_Board) OR (isInSharedBoard AND (assignedToMe OR (hasDueDate AND noAssignees)))
+ "and (c.done is null or c.done = 0) " +
+ // Full Logic: (hasDueDate AND isIn_PRIVATE_Board) OR (isInSharedBoard AND (assignedToMe OR (hasDueDate AND noAssignees)))
"and (" +
"(c.dueDate is not null AND NOT exists(select 1 from AccessControl ac where ac.boardId = b.localId and ac.status <> 3))" + //(hasDueDate AND isInPrivateBoard)
"OR (" +
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/database/migration/Migration_32_33.java b/app/src/main/java/it/niedermann/nextcloud/deck/database/migration/Migration_32_33.java
new file mode 100644
index 000000000..d6938dda6
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/database/migration/Migration_32_33.java
@@ -0,0 +1,25 @@
+package it.niedermann.nextcloud.deck.database.migration;
+
+import androidx.annotation.NonNull;
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+/**
+ * Adds support for marking a card as done: https://github.com/stefan-niedermann/nextcloud-deck/issues/1556
+ */
+public class Migration_32_33 extends Migration {
+
+ public Migration_32_33() {
+ super(32, 33);
+ }
+
+ @Override
+ public void migrate(@NonNull SupportSQLiteDatabase database) {
+ database.execSQL("ALTER TABLE `Card` add column done INTEGER");
+ // Reset ETags: Refetch all cards to support Done state which did not change ETags
+ database.execSQL("UPDATE `Account` SET `boardsEtag` = NULL");
+ database.execSQL("UPDATE `Board` SET `etag` = NULL");
+ database.execSQL("UPDATE `Stack` SET `etag` = NULL");
+ database.execSQL("UPDATE `Card` SET `etag` = NULL");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/model/Card.java b/app/src/main/java/it/niedermann/nextcloud/deck/model/Card.java
index a5650f124..676753245 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/model/Card.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/model/Card.java
@@ -57,6 +57,7 @@ public class Card extends AbstractRemoteEntity {
private String type;
private Instant createdAt;
private Instant deletedAt;
+ private Instant done;
private int attachmentCount;
private Long userId;
@@ -91,6 +92,7 @@ public class Card extends AbstractRemoteEntity {
this.order = card.getOrder();
this.archived = card.isArchived();
this.dueDate = card.getDueDate();
+ this.done = card.getDone();
this.notified = card.isNotified();
this.overdue = card.getOverdue();
this.commentsUnread = card.getCommentsUnread();
@@ -252,6 +254,14 @@ public class Card extends AbstractRemoteEntity {
return this.order;
}
+ public Instant getDone() {
+ return done;
+ }
+
+ public void setDone(Instant done) {
+ this.done = done;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -274,6 +284,8 @@ public class Card extends AbstractRemoteEntity {
return false;
if (deletedAt != null ? !deletedAt.equals(card.deletedAt) : card.deletedAt != null)
return false;
+ if (done != null ? !done.equals(card.done) : card.done != null)
+ return false;
if (userId != null ? !userId.equals(card.userId) : card.userId != null) return false;
return dueDate != null ? dueDate.equals(card.dueDate) : card.dueDate == null;
}
@@ -286,6 +298,7 @@ public class Card extends AbstractRemoteEntity {
result = 31 * result + (type != null ? type.hashCode() : 0);
result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);
result = 31 * result + (deletedAt != null ? deletedAt.hashCode() : 0);
+ result = 31 * result + (done != null ? done.hashCode() : 0);
result = 31 * result + attachmentCount;
result = 31 * result + (userId != null ? userId.hashCode() : 0);
result = 31 * result + order;
@@ -306,6 +319,7 @@ public class Card extends AbstractRemoteEntity {
", type='" + type + '\'' +
", createdAt=" + createdAt +
", deletedAt=" + deletedAt +
+ ", done=" + done +
", attachmentCount=" + attachmentCount +
", userId=" + userId +
", order=" + order +
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/model/enums/EDoneType.java b/app/src/main/java/it/niedermann/nextcloud/deck/model/enums/EDoneType.java
new file mode 100644
index 000000000..4222ee487
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/model/enums/EDoneType.java
@@ -0,0 +1,40 @@
+package it.niedermann.nextcloud.deck.model.enums;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+
+import it.niedermann.nextcloud.deck.R;
+
+public enum EDoneType {
+ NO_FILTER(1, R.string.filter_done_no_filter),
+ DONE(2, R.string.filter_done_done),
+ UNDONE(3, R.string.filter_done_undone);
+
+ private final int value;
+ private final int id;
+
+ EDoneType(int id, @StringRes int value) {
+ this.value = value;
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public static EDoneType findById(int id) {
+ for (EDoneType s : EDoneType.values()) {
+ if (s.getId() == id) {
+ return s;
+ }
+ }
+ throw new IllegalArgumentException("unknown " + EDoneType.class.getSimpleName() + " key: " + id);
+ }
+
+ @NonNull
+ public String toString(Context context) {
+ return context.getString(this.value);
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/model/internal/FilterInformation.java b/app/src/main/java/it/niedermann/nextcloud/deck/model/internal/FilterInformation.java
index da0501779..8c7da2b24 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/model/internal/FilterInformation.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/model/internal/FilterInformation.java
@@ -9,6 +9,7 @@ import java.util.List;
import it.niedermann.nextcloud.deck.model.Label;
import it.niedermann.nextcloud.deck.model.User;
+import it.niedermann.nextcloud.deck.model.enums.EDoneType;
import it.niedermann.nextcloud.deck.model.enums.EDueType;
import it.niedermann.nextcloud.deck.model.ocs.projects.OcsProject;
@@ -20,6 +21,8 @@ public class FilterInformation implements Serializable {
@NonNull
private EDueType dueType = EDueType.NO_FILTER;
+ @NonNull
+ private EDoneType doneType = EDoneType.NO_FILTER;
private boolean noAssignedLabel = false;
private boolean noAssignedUser = false;
private boolean noAssignedProject = false;
@@ -41,6 +44,7 @@ public class FilterInformation implements Serializable {
public FilterInformation(@Nullable FilterInformation filterInformation) {
if (filterInformation != null) {
this.dueType = filterInformation.getDueType();
+ this.doneType = filterInformation.getDoneType();
this.archiveStatus = filterInformation.getArchiveStatus();
this.users.addAll(filterInformation.getUsers());
this.labels.addAll(filterInformation.getLabels());
@@ -72,6 +76,15 @@ public class FilterInformation implements Serializable {
}
@NonNull
+ public EDoneType getDoneType() {
+ return doneType;
+ }
+
+ public void setDoneType(@NonNull EDoneType doneType) {
+ this.doneType = doneType;
+ }
+
+ @NonNull
public List<User> getUsers() {
return users;
}
@@ -152,6 +165,7 @@ public class FilterInformation implements Serializable {
public String toString() {
return "FilterInformation{" +
"dueType=" + dueType +
+ ", doneType=" + doneType +
", noAssignedLabel=" + noAssignedLabel +
", noAssignedUser=" + noAssignedUser +
", users=" + users +
@@ -169,6 +183,7 @@ public class FilterInformation implements Serializable {
return false;
}
return !(filterInformation.getDueType() == EDueType.NO_FILTER
+ && filterInformation.getDoneType() == EDoneType.NO_FILTER
&& filterInformation.getUsers().isEmpty()
&& filterInformation.getProjects().isEmpty()
&& filterInformation.getLabels().isEmpty()
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/model/ocs/Version.java b/app/src/main/java/it/niedermann/nextcloud/deck/model/ocs/Version.java
index 355307ce0..7a6aba31d 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/model/ocs/Version.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/model/ocs/Version.java
@@ -9,6 +9,7 @@ import java.util.regex.Pattern;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.model.Attachment;
+import it.niedermann.nextcloud.deck.model.Card;
import it.niedermann.nextcloud.deck.model.ocs.comment.DeckComment;
public class Version implements Comparable<Version> {
@@ -17,6 +18,8 @@ public class Version implements Comparable<Version> {
private static final Version VERSION_1_0_0 = new Version("1.0.0", 1, 0, 0);
private static final Version VERSION_1_0_3 = new Version("1.0.3", 1, 0, 3);
private static final Version VERSION_1_3_0 = new Version("1.3.0", 1, 3, 0);
+ private static final Version VERSION_1_12_0 = new Version("1.12.0", 1, 12, 0);
+ private static final Version VERSION_1_12_2 = new Version("1.12.2", 1, 12, 2);
private String originalVersion = "?";
private final int major;
@@ -137,7 +140,7 @@ public class Version implements Comparable<Version> {
}
/**
- * {@link DeckComment} API only available starting with {@link Version} 1.0.0-alpha1
+ * {@link DeckComment} API only available starting with {@link Version} <code>1.0.0-alpha1</code>
*
* @return whether or not the server supports the {@link DeckComment} API
*/
@@ -147,12 +150,12 @@ public class Version implements Comparable<Version> {
/**
* Replying to a {@link DeckComment} does cause synchronization errors because the API expected the
- * <code>parentId</code> to be a {@link String} up until {@link Version} 1.0.3
- * https://github.com/nextcloud/deck/issues/1831#issuecomment-627207849
+ * <code>parentId</code> to be a {@link String} up until {@link #VERSION_1_0_3}
*
* @return whether or not the server supports replying to comments
+ * @see <a href="https://github.com/nextcloud/deck/issues/1831#issuecomment-627207849">Deck server issue #1831</a>
*/
- public boolean supportsCommentsReplys() {
+ public boolean supportsCommentsReplies() {
return isGreaterOrEqualTo(VERSION_1_0_3);
}
@@ -171,15 +174,25 @@ public class Version implements Comparable<Version> {
}
/**
- * Title max length has been increased from 100 to 255 characters beginning with server {@link Version} 1.0.0
+ * Cards started to have an additional property called <a href="https://github.com/nextcloud/deck/pull/4137"><code>done</code></a> with version <a href="https://github.com/nextcloud/deck/releases/tag/v1.12.0">{@link #VERSION_1_12_0}</a> of the Deck server app.
+ * However, there was an <a href="https://github.com/nextcloud/deck/issues/534#issuecomment-1892061055">issue that would have required to call a second endpoint when marking a card as <code>undone</code></a> which was <a href="https://github.com/nextcloud/deck/pull/5491">fixed</a> in {@link #VERSION_1_12_2}.
+ * We therefore support the <code>done</code> property only starting with {@link #VERSION_1_12_2}.
+ *
+ * @return whether or not the server supports the {@link Card#getDone()} state
+ * @see <a href="https://github.com/nextcloud/deck/issues/534">Deck server issue #534</a>
+ */
+ public boolean supportsDone() {
+ return isGreaterOrEqualTo(VERSION_1_12_2);
+ }
+
+ /**
+ * Title max length has been increased from <code>100</code> to <code>255</code> characters beginning with server {@link #VERSION_1_0_0}
*
* @return the number of characters that the title fields of cards allow
* @see <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/422">issue</a>
*/
public int getCardTitleMaxLength() {
- return isGreaterOrEqualTo(VERSION_1_0_0)
- ? 255
- : 100;
+ return isGreaterOrEqualTo(VERSION_1_0_0) ? 255 : 100;
}
/**
@@ -194,15 +207,19 @@ public class Version implements Comparable<Version> {
}
/**
- * URL to view a card in the web interface has been changed in {@link Version} 1.0.0
+ * URL to view a card in the web interface has been changed in {@link #VERSION_1_0_0}
*
* @return the id of the string resource which contains the partial URL to open a card in the web UI
* @see <a href="https://github.com/nextcloud/deck/pull/1977">documentation in PR</a>
*/
@StringRes
public int getShareLinkResource() {
- return isGreaterOrEqualTo(VERSION_1_0_0)
- ? R.string.url_fragment_share_card_since_1_0_0
- : R.string.url_fragment_share_card_pre_1_0_0;
+ if (isGreaterOrEqualTo(VERSION_1_12_0)) { // Probably even earlier, but there are likely redirects
+ return R.string.url_fragment_share_card_since_1_12_0;
+ } else if (isGreaterOrEqualTo(VERSION_1_0_0)) {
+ return R.string.url_fragment_share_card_since_1_0_0;
+ } else {
+ return R.string.url_fragment_share_card_pre_1_0_0;
+ }
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/model/propagation/CardUpdate.java b/app/src/main/java/it/niedermann/nextcloud/deck/model/propagation/CardUpdate.java
index b13b84e36..389e26489 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/model/propagation/CardUpdate.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/model/propagation/CardUpdate.java
@@ -27,6 +27,7 @@ public class CardUpdate extends Card {
setAccountId(card.getAccountId());
setId(card.getId());
setLocalId(card.getLocalId());
+ setDone(card.getCard().getDone());
}
public User getOwner() {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/remote/api/JsonToEntityParser.java b/app/src/main/java/it/niedermann/nextcloud/deck/remote/api/JsonToEntityParser.java
index 04a0b706e..5c2a83dff 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/remote/api/JsonToEntityParser.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/remote/api/JsonToEntityParser.java
@@ -408,6 +408,7 @@ public class JsonToEntityParser {
card.setLastModified(getTimestampFromLong(e.get("lastModified")));
card.setCreatedAt(getTimestampFromLong(e.get("createdAt")));
card.setDeletedAt(getTimestampFromLong(e.get("deletedAt")));
+ card.setDone(getTimestampFromString(e.get("done")));
if (e.has("labels") && !e.get("labels").isJsonNull()) {
JsonArray labelsJson = e.getAsJsonArray("labels");
List<Label> labels = new ArrayList<>();
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 7f976970a..2f9671ce5 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
@@ -24,7 +24,6 @@ import java.util.Objects;
import java.util.stream.Collectors;
import it.niedermann.android.reactivelivedata.ReactiveLiveData;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogAccountSwitcherBinding;
import it.niedermann.nextcloud.deck.ui.ImportAccountActivity;
@@ -76,7 +75,7 @@ public class AccountSwitcherDialog extends DialogFragment {
binding.accountHost.setText(Uri.parse(currentAccount.getUrl()).getHost());
Glide.with(requireContext())
- .load(currentAccount.getAvatarUrl(DimensionUtil.INSTANCE.dpToPx(binding.currentAccountItemAvatar.getContext(), R.dimen.avatar_size)))
+ .load(currentAccount.getAvatarUrl(binding.currentAccountItemAvatar.getResources().getDimensionPixelSize(R.dimen.avatar_size)))
.apply(RequestOptions.circleCropTransform())
.placeholder(R.drawable.ic_baseline_account_circle_24)
.error(R.drawable.ic_baseline_account_circle_24)
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 6d635b9d6..f3c61c3ce 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
@@ -11,7 +11,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.ItemAccountChooseBinding;
import it.niedermann.nextcloud.deck.model.Account;
@@ -34,7 +33,7 @@ public class AccountSwitcherViewHolder extends RecyclerView.ViewHolder {
);
binding.accountHost.setText(Uri.parse(account.getUrl()).getHost());
Glide.with(itemView.getContext())
- .load(account.getAvatarUrl(DimensionUtil.INSTANCE.dpToPx(binding.accountItemAvatar.getContext(), R.dimen.avatar_size)))
+ .load(account.getAvatarUrl(binding.accountItemAvatar.getResources().getDimensionPixelSize(R.dimen.avatar_size)))
.apply(RequestOptions.circleCropTransform())
.placeholder(R.drawable.ic_baseline_account_circle_24)
.error(R.drawable.ic_baseline_account_circle_24)
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlAdapter.java
index bb6add7f4..0c813d04e 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlAdapter.java
@@ -16,7 +16,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ItemAccessControlBinding;
import it.niedermann.nextcloud.deck.databinding.ItemAccessControlOwnerBinding;
@@ -82,7 +81,7 @@ public class AccessControlAdapter extends RecyclerView.Adapter<RecyclerView.View
final var ownerHolder = (OwnerViewHolder) holder;
ownerHolder.binding.owner.setText(ac.getUser().getDisplayname());
Glide.with(ownerHolder.binding.avatar.getContext())
- .load(account.getAvatarUrl(DimensionUtil.INSTANCE.dpToPx(ownerHolder.binding.avatar.getContext(), R.dimen.avatar_size), ac.getUser().getUid()))
+ .load(account.getAvatarUrl(ownerHolder.binding.avatar.getResources().getDimensionPixelSize(R.dimen.avatar_size), ac.getUser().getUid()))
.apply(RequestOptions.circleCropTransform())
.placeholder(R.drawable.ic_person_grey600_24dp)
.error(R.drawable.ic_person_grey600_24dp)
@@ -93,7 +92,7 @@ public class AccessControlAdapter extends RecyclerView.Adapter<RecyclerView.View
default: {
final var acHolder = (AccessControlViewHolder) holder;
Glide.with(acHolder.binding.avatar.getContext())
- .load(account.getAvatarUrl(DimensionUtil.INSTANCE.dpToPx(acHolder.binding.avatar.getContext(), R.dimen.avatar_size), ac.getUser().getUid()))
+ .load(account.getAvatarUrl(acHolder.binding.avatar.getResources().getDimensionPixelSize(R.dimen.avatar_size), ac.getUser().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/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);
+ }
+}
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 8eac0dbb4..fc722226a 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
@@ -19,6 +19,7 @@ import com.nextcloud.android.common.ui.theme.utils.ColorRole;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogFilterBinding;
+import it.niedermann.nextcloud.deck.model.enums.EDoneType;
import it.niedermann.nextcloud.deck.model.enums.EDueType;
import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
import it.niedermann.nextcloud.deck.ui.theme.ThemedDialogFragment;
@@ -32,6 +33,7 @@ public class FilterDialogFragment extends ThemedDialogFragment {
private final static int[] tabTitles = new int[]{
R.string.filter_tags_title,
R.string.filter_user_title,
+ R.string.filter_done_title,
R.string.filter_duedate_title
};
@@ -63,6 +65,9 @@ public class FilterDialogFragment extends ThemedDialogFragment {
tab.setIcon(draft.getUsers().size() > 0 || draft.isNoAssignedUser() ? indicator : null);
break;
case 2:
+ tab.setIcon(draft.getDoneType() != EDoneType.NO_FILTER ? indicator : null);
+ break;
+ case 3:
tab.setIcon(draft.getDueType() != EDueType.NO_FILTER ? indicator : null);
break;
default:
@@ -86,7 +91,7 @@ public class FilterDialogFragment extends ThemedDialogFragment {
.setTitle(R.string.simple_filter)
.setView(binding.getRoot())
.setNeutralButton(android.R.string.cancel, null)
- .setNegativeButton(R.string.simple_clear, (a, b) -> filterViewModel.clearFilterInformation(false))
+ .setNegativeButton(R.string.simple_reset, (a, b) -> filterViewModel.clearFilterInformation(false))
.setPositiveButton(R.string.simple_filter, (a, b) -> filterViewModel.publishFilterInformationDraft())
.create();
}
@@ -124,6 +129,8 @@ public class FilterDialogFragment extends ThemedDialogFragment {
case 1:
return new FilterUserFragment();
case 2:
+ return new FilterDoneTypeFragment();
+ case 3:
return new FilterDueTypeFragment();
default:
throw new IllegalArgumentException("position must be between 0 and 2 but was " + position);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDoneTypeAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDoneTypeAdapter.java
new file mode 100644
index 000000000..d194f78ab
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDoneTypeAdapter.java
@@ -0,0 +1,96 @@
+package it.niedermann.nextcloud.deck.ui.filter;
+
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.Arrays;
+
+import it.niedermann.nextcloud.deck.databinding.ItemFilterDonetypeBinding;
+import it.niedermann.nextcloud.deck.model.enums.EDoneType;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.Themed;
+
+public class FilterDoneTypeAdapter extends RecyclerView.Adapter<FilterDoneTypeAdapter.DoneTypeViewHolder> {
+ @NonNull
+ private final EDoneType[] doneTypes = EDoneType.values();
+ private int selectedDoneTypePosition;
+ @Nullable
+ private final SelectionListener<EDoneType> selectionListener;
+ @ColorInt
+ private final int color;
+
+ @SuppressWarnings("WeakerAccess")
+ public FilterDoneTypeAdapter(@NonNull EDoneType selectedDoneType, @Nullable SelectionListener<EDoneType> selectionListener, @ColorInt int color) {
+ super();
+ this.selectedDoneTypePosition = Arrays.binarySearch(doneTypes, selectedDoneType);
+ this.selectionListener = selectionListener;
+ this.color = color;
+ setHasStableIds(true);
+ }
+
+ @NonNull
+ @Override
+ public DoneTypeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new DoneTypeViewHolder(ItemFilterDonetypeBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull DoneTypeViewHolder viewHolder, int position) {
+ viewHolder.bind(doneTypes[position]);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public int getItemCount() {
+ return doneTypes.length;
+ }
+
+ class DoneTypeViewHolder extends RecyclerView.ViewHolder implements Themed {
+ private final ItemFilterDonetypeBinding binding;
+
+ DoneTypeViewHolder(@NonNull ItemFilterDonetypeBinding binding) {
+ super(binding.getRoot());
+ this.binding = binding;
+ }
+
+ void bind(final EDoneType doneType) {
+ binding.doneType.setText(doneType.toString(binding.doneType.getContext()));
+ itemView.setSelected(doneTypes[selectedDoneTypePosition].equals(doneType));
+ applyTheme(color);
+
+ itemView.setOnClickListener(view -> {
+ final int oldSelection = selectedDoneTypePosition;
+ if (doneTypes[selectedDoneTypePosition].equals(doneType)) {
+ selectedDoneTypePosition = Arrays.binarySearch(doneTypes, EDoneType.NO_FILTER);
+ itemView.setSelected(false);
+ if (selectionListener != null) {
+ selectionListener.onItemSelected(EDoneType.NO_FILTER);
+ }
+ notifyItemChanged(selectedDoneTypePosition);
+ } else {
+ selectedDoneTypePosition = Arrays.binarySearch(doneTypes, doneType);
+ itemView.setSelected(true);
+ if (selectionListener != null) {
+ selectionListener.onItemSelected(doneType);
+ }
+ }
+ notifyItemChanged(oldSelection);
+ });
+ }
+
+ @Override
+ public void applyTheme(int color) {
+ 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/FilterDoneTypeFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDoneTypeFragment.java
new file mode 100644
index 000000000..8cee39d1e
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDoneTypeFragment.java
@@ -0,0 +1,47 @@
+package it.niedermann.nextcloud.deck.ui.filter;
+
+import static java.util.Objects.requireNonNull;
+
+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.DialogFilterDoneBinding;
+import it.niedermann.nextcloud.deck.model.enums.EDoneType;
+
+public class FilterDoneTypeFragment extends Fragment implements SelectionListener<EDoneType> {
+
+ private FilterViewModel filterViewModel;
+ private DialogFilterDoneBinding binding;
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ binding = DialogFilterDoneBinding.inflate(requireActivity().getLayoutInflater());
+
+ filterViewModel = new ViewModelProvider(requireActivity()).get(FilterViewModel.class);
+
+ binding.doneType.setItemAnimator(null);
+ filterViewModel.getCurrentBoardColor$().observe(getViewLifecycleOwner(),
+ color -> binding.doneType.setAdapter(new FilterDoneTypeAdapter(requireNonNull(filterViewModel.getFilterInformationDraft().getValue()).getDoneType(), this, color)));
+
+ return binding.getRoot();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ this.binding = null;
+ }
+
+ @Override
+ public void onItemSelected(EDoneType item) {
+ filterViewModel.setFilterInformationDraftDoneType(item);
+ }
+}
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 fec2186a1..1657efdff 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
@@ -15,7 +15,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ItemFilterUserBinding;
import it.niedermann.nextcloud.deck.model.Account;
@@ -89,7 +88,7 @@ public class FilterUserAdapter extends RecyclerView.Adapter<FilterUserAdapter.Us
void bind(@NonNull final User user) {
binding.title.setText(user.getDisplayname());
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/filter/FilterViewModel.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterViewModel.java
index 09f2f4fa1..5bd226e9f 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterViewModel.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterViewModel.java
@@ -15,6 +15,7 @@ import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.Label;
import it.niedermann.nextcloud.deck.model.User;
+import it.niedermann.nextcloud.deck.model.enums.EDoneType;
import it.niedermann.nextcloud.deck.model.enums.EDueType;
import it.niedermann.nextcloud.deck.model.internal.FilterInformation;
import it.niedermann.nextcloud.deck.ui.viewmodel.BaseViewModel;
@@ -80,6 +81,12 @@ public class FilterViewModel extends BaseViewModel {
this.filterInformationDraft.postValue(newDraft);
}
+ public void setFilterInformationDraftDoneType(@NonNull EDoneType doneType) {
+ final var newDraft = new FilterInformation(filterInformationDraft.getValue());
+ newDraft.setDoneType(doneType);
+ this.filterInformationDraft.postValue(newDraft);
+ }
+
public void addFilterInformationDraftLabel(@NonNull Label label) {
final var newDraft = new FilterInformation(filterInformationDraft.getValue());
newDraft.addLabel(label);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/main/search/SearchCardViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/main/search/SearchCardViewHolder.java
index 868d9c877..29a7373d1 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/main/search/SearchCardViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/main/search/SearchCardViewHolder.java
@@ -18,7 +18,6 @@ import org.jetbrains.annotations.Contract;
import java.util.List;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ItemSearchCardBinding;
import it.niedermann.nextcloud.deck.model.Account;
@@ -64,7 +63,7 @@ public class SearchCardViewHolder extends SearchViewHolder {
.load(new SingleSignOnUrl(account.getName(), AttachmentUtil.getThumbnailUrl(account, fullCard.getId(), coverImages.get(), binding.coverImages.getWidth())))
.apply(new RequestOptions().transform(
new CenterCrop(),
- new RoundedCorners(DimensionUtil.INSTANCE.dpToPx(context, R.dimen.spacer_1x))
+ new RoundedCorners(context.getResources().getDimensionPixelSize(R.dimen.spacer_1x))
))
.placeholder(R.drawable.ic_image_grey600_24dp)
.error(R.drawable.ic_image_grey600_24dp)
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 c4684fe55..10249fc5b 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
@@ -15,7 +15,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.ItemAccountChooseBinding;
import it.niedermann.nextcloud.deck.model.Account;
@@ -38,7 +37,7 @@ public class ManageAccountViewHolder extends RecyclerView.ViewHolder {
);
binding.accountHost.setText(Uri.parse(account.getUrl()).getHost());
Glide.with(itemView.getContext())
- .load(account.getAvatarUrl(DimensionUtil.INSTANCE.dpToPx(binding.accountItemAvatar.getContext(), R.dimen.avatar_size)))
+ .load(account.getAvatarUrl(binding.accountItemAvatar.getResources().getDimensionPixelSize(R.dimen.avatar_size)))
.apply(RequestOptions.circleCropTransform())
.placeholder(R.drawable.ic_baseline_account_circle_24)
.error(R.drawable.ic_baseline_account_circle_24)
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/AccountAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/AccountAdapter.java
index bf919cd66..279540b72 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/AccountAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/AccountAdapter.java
@@ -11,7 +11,6 @@ import com.bumptech.glide.request.RequestOptions;
import java.net.URL;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ItemPrepareCreateAccountBinding;
@@ -49,7 +48,7 @@ public class AccountAdapter extends AbstractAdapter<Account> {
}
Glide.with(getContext())
- .load(account.getAvatarUrl(DimensionUtil.INSTANCE.dpToPx(binding.avatar.getContext(), R.dimen.avatar_size)))
+ .load(account.getAvatarUrl(binding.avatar.getResources().getDimensionPixelSize(R.dimen.avatar_size)))
.placeholder(R.drawable.ic_baseline_account_circle_24)
.error(R.drawable.ic_baseline_account_circle_24)
.apply(RequestOptions.circleCropTransform())
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 7b8c81ab4..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 @@ package it.niedermann.nextcloud.deck.ui.theme;
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.LayerDrawable;
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.annotation.Nullable;
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.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.R;
@@ -195,36 +191,6 @@ public class DeckViewThemeUtils extends ViewThemeUtilsBase {
return Optional.empty();
}
-
- @Deprecated(forRemoval = true)
- public static void themeDueDate(@NonNull TextView cardDueDate, @NonNull LocalDate dueDate) {
- final var context = cardDueDate.getContext();
- final long diff = DAYS.between(LocalDate.now(), dueDate);
-
- @ColorInt @Nullable Integer textColor = null;
- @DrawableRes int backgroundDrawable = 0;
-
- if (diff == 1) {
- // due date: tomorrow
- backgroundDrawable = R.drawable.due_tomorrow_background;
- textColor = ContextCompat.getColor(context, R.color.due_text_tomorrow);
- } else 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);
- }
-
- 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/theme/ThemedDatePickerDialog.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedDatePickerDialog.java
index 926a394e4..a78bc972f 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedDatePickerDialog.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedDatePickerDialog.java
@@ -36,11 +36,11 @@ public class ThemedDatePickerDialog extends DatePickerDialog implements Themed {
public void applyTheme(int color) {
final var scheme = ThemeUtils.createScheme(color, requireContext());
- @ColorInt final int buttonTextColor = scheme.getOnPrimaryContainer();
+ @ColorInt final int buttonTextColor = scheme.getOnSecondaryContainer();
setOkColor(buttonTextColor);
setCancelColor(buttonTextColor);
- setAccentColor(Scheme.dark(color).getPrimaryContainer());
+ setAccentColor(Scheme.dark(color).getSecondaryContainer());
}
/**
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedTimePickerDialog.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedTimePickerDialog.java
index d835a5723..f9bc8bd13 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedTimePickerDialog.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedTimePickerDialog.java
@@ -36,11 +36,11 @@ public class ThemedTimePickerDialog extends TimePickerDialog implements Themed {
public void applyTheme(int color) {
final var scheme = ThemeUtils.createScheme(color, requireContext());
- @ColorInt final int buttonTextColor = scheme.getOnPrimaryContainer();
+ @ColorInt final int buttonTextColor = scheme.getOnSecondaryContainer();
setOkColor(buttonTextColor);
setCancelColor(buttonTextColor);
- setAccentColor(Scheme.dark(color).getPrimaryContainer());
+ setAccentColor(Scheme.dark(color).getSecondaryContainer());
}
/**
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsUtil.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsUtil.java
index 2341c6590..30ba2296c 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsUtil.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsUtil.java
@@ -1,5 +1,7 @@
package it.niedermann.nextcloud.deck.ui.upcomingcards;
+import static java.time.temporal.ChronoUnit.DAYS;
+
import android.content.Context;
import androidx.annotation.NonNull;
@@ -17,8 +19,6 @@ import java.util.List;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.model.Card;
-import static java.time.temporal.ChronoUnit.DAYS;
-
public class UpcomingCardsUtil {
private UpcomingCardsUtil() {
@@ -31,7 +31,7 @@ public class UpcomingCardsUtil {
return EUpcomingDueType.NO_DUE;
}
- long diff = DAYS.between(LocalDate.now(), dueDate.atZone(ZoneId.systemDefault()).toLocalDate());
+ final long diff = DAYS.between(LocalDate.now(), dueDate.atZone(ZoneId.systemDefault()).toLocalDate());
if (diff > 7) {
return EUpcomingDueType.LATER;
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/ColorChooser.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/ColorChooser.java
index ae520cf91..a653feac8 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/ColorChooser.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/ColorChooser.java
@@ -18,7 +18,6 @@ import com.skydoves.colorpickerview.listeners.ColorEnvelopeListener;
import java.util.Arrays;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.WidgetColorChooserBinding;
import it.niedermann.nextcloud.deck.ui.theme.DeckViewThemeUtils;
@@ -45,7 +44,7 @@ public class ColorChooser extends LinearLayout {
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
- params.setMargins(0, DimensionUtil.INSTANCE.dpToPx(context, R.dimen.spacer_1x), 0, 0);
+ params.setMargins(0, getResources().getDimensionPixelSize(R.dimen.spacer_1x), 0, 0);
params.setFlexBasisPercent(.15f);
final var styles = context.obtainStyledAttributes(attrs, R.styleable.ColorChooser, 0, 0);
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..095a46bd3
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/DueDateChip.java
@@ -0,0 +1,111 @@
+package it.niedermann.nextcloud.deck.ui.view;
+
+import static java.time.temporal.ChronoUnit.HOURS;
+
+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.LocalDateTime;
+import java.time.ZoneId;
+
+import it.niedermann.nextcloud.deck.R;
+import it.niedermann.nextcloud.deck.util.DateUtil;
+
+public class DueDateChip extends Chip {
+
+ @ColorInt
+ protected final int colorOnSurface;
+ protected final boolean compactMode;
+
+ public DueDateChip(Context context) {
+ this(context, null);
+ }
+
+ public DueDateChip(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.chipStyle);
+ }
+
+ public DueDateChip(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ final var typedValue = new TypedValue();
+ final var theme = getContext().getTheme();
+ theme.resolveAttribute(R.attr.colorOnSurfaceVariant, 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);
+ setClickable(false);
+
+ @Px final var padding = getResources().getDimensionPixelSize(R.dimen.spacer_1x);
+ setPadding(padding, padding, padding, padding);
+ setMinHeight(0);
+ setChipMinHeight(0);
+
+ if (compactMode) {
+ setChipEndPadding(0);
+ setTextEndPadding(0);
+ }
+ }
+
+ public void setDueDate(@NonNull Instant date, boolean isDone) {
+ if (compactMode) {
+ setText(null);
+ } else {
+ 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_circle_24;
+ backgroundColorRes = R.color.due_done;
+ textColorRes = R.color.due_text_done;
+
+ } 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));
+ 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/java/it/niedermann/nextcloud/deck/ui/view/OverlappingAvatars.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/OverlappingAvatars.java
index c1d5af3a2..4c52ffc1a 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/OverlappingAvatars.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/OverlappingAvatars.java
@@ -16,7 +16,6 @@ import com.bumptech.glide.request.RequestOptions;
import java.util.List;
-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;
@@ -41,10 +40,12 @@ public class OverlappingAvatars extends RelativeLayout {
public OverlappingAvatars(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- maxAvatarCount = context.getResources().getInteger(R.integer.max_avatar_count);
- avatarBorderSize = DimensionUtil.INSTANCE.dpToPx(context, R.dimen.avatar_size_small_overlapping_border);
- avatarSize = DimensionUtil.INSTANCE.dpToPx(context, R.dimen.avatar_size_small) + avatarBorderSize * 2;
- overlapPx = DimensionUtil.INSTANCE.dpToPx(context, R.dimen.avatar_size_small_overlapping);
+
+ final var resources = getResources();
+ maxAvatarCount = resources.getInteger(R.integer.max_avatar_count);
+ avatarBorderSize = resources.getDimensionPixelSize(R.dimen.avatar_size_small_overlapping_border);
+ avatarSize = resources.getDimensionPixelSize(R.dimen.avatar_size_small) + avatarBorderSize * 2;
+ overlapPx = resources.getDimensionPixelSize(R.dimen.avatar_size_small_overlapping);
borderDrawable = ContextCompat.getDrawable(context, R.drawable.avatar_border);
assert borderDrawable != null;
DrawableCompat.setTint(borderDrawable, ContextCompat.getColor(context, R.color.bg_card));
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/labelchip/CompactLabelChip.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/labelchip/CompactLabelChip.java
index a2a50430c..3516b036b 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/labelchip/CompactLabelChip.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/labelchip/CompactLabelChip.java
@@ -6,7 +6,6 @@ import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Px;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.model.Label;
@@ -16,6 +15,6 @@ public class CompactLabelChip extends LabelChip {
public CompactLabelChip(@NonNull Context context, @NonNull Label label, @Px int gutter) {
super(context, label, gutter);
params.setFlexBasisPercent(1 / 6.5f);
- setHeight(DimensionUtil.INSTANCE.dpToPx(context, R.dimen.compact_label_height));
+ setHeight(getResources().getDimensionPixelSize(R.dimen.compact_label_height));
}
} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/labellayout/LabelLayout.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/labellayout/LabelLayout.java
index 526bdbaef..ce7e38262 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/labellayout/LabelLayout.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/labellayout/LabelLayout.java
@@ -11,7 +11,6 @@ import com.google.android.flexbox.FlexboxLayout;
import java.util.LinkedList;
import java.util.List;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.model.Label;
@@ -26,7 +25,7 @@ public abstract class LabelLayout extends FlexboxLayout {
public LabelLayout(Context context, AttributeSet attrs) {
super(context, attrs);
- this.gutter = DimensionUtil.INSTANCE.dpToPx(context, R.dimen.spacer_1hx);
+ this.gutter = context.getResources().getDimensionPixelSize(R.dimen.spacer_1hx);
}
/**
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SingleCardWidget.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SingleCardWidget.java
index 08e32bf25..f674047cc 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SingleCardWidget.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SingleCardWidget.java
@@ -13,9 +13,11 @@ import android.text.TextUtils;
import android.view.View;
import android.widget.RemoteViews;
+import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
+import java.time.Instant;
import java.util.NoSuchElementException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -53,19 +55,31 @@ public class SingleCardWidget extends AppWidgetProvider {
views.setViewVisibility(R.id.description_lv, View.VISIBLE);
}
+ final var card = fullModel.getFullCard().getCard();
+
views.setOnClickPendingIntent(R.id.widget_card, pendingIntent);
views.setPendingIntentTemplate(R.id.description_lv, pendingIntent);
- views.setTextViewText(R.id.title, fullModel.getFullCard().getCard().getTitle());
+ views.setTextViewText(R.id.title, card.getTitle());
views.setRemoteAdapter(R.id.description_lv, serviceIntent);
- if (fullModel.getFullCard().getCard().getDueDate() != null) {
- views.setTextViewText(R.id.card_due_date, DateUtil.getRelativeDateTimeString(context, fullModel.getFullCard().getCard().getDueDate().toEpochMilli()));
- // TODO Use multiple views for background colors and only set the necessary to View.VISIBLE
- // https://stackoverflow.com/a/3376537
- // Because otherwise using Reflection is the only way
+ // TODO Use multiple views for background colors and only set the necessary to View.VISIBLE
+ // https://stackoverflow.com/a/3376537
+ // Because otherwise using Reflection is the only way
+ if (card.getDone() != null) {
+ views.setTextViewText(R.id.card_due_date, DateUtil.getRelativeDateTimeString(context, card.getDone().toEpochMilli()));
+ views.setViewVisibility(R.id.card_due_date, View.VISIBLE);
+ views.setViewVisibility(R.id.card_due_date_image, View.VISIBLE);
+ views.setImageViewResource(R.id.card_due_date_image, R.drawable.ic_check_circle_24);
+ } else if (card.getDueDate() != null) {
+ views.setTextViewText(R.id.card_due_date, DateUtil.getRelativeDateTimeString(context, card.getDueDate().toEpochMilli()));
views.setViewVisibility(R.id.card_due_date, View.VISIBLE);
views.setViewVisibility(R.id.card_due_date_image, View.VISIBLE);
- views.setImageViewResource(R.id.card_due_date_image, R.drawable.calendar_blank_grey600_24dp);
+
+ @DrawableRes final var dueDateImage = card.getDueDate().isBefore(Instant.now())
+ ? R.drawable.ic_time_filled_24
+ : R.drawable.ic_time_24;
+
+ views.setImageViewResource(R.id.card_due_date_image, dueDateImage);
} else {
views.setViewVisibility(R.id.card_due_date, View.GONE);
views.setViewVisibility(R.id.card_due_date_image, View.GONE);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/upcoming/UpcomingWidgetFactory.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/upcoming/UpcomingWidgetFactory.java
index d7c320a95..902d82d88 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/upcoming/UpcomingWidgetFactory.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/upcoming/UpcomingWidgetFactory.java
@@ -12,7 +12,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
-import it.niedermann.android.util.DimensionUtil;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.model.full.FullCard;
@@ -35,8 +34,10 @@ public class UpcomingWidgetFactory implements RemoteViewsService.RemoteViewsFact
this.context = context;
this.appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
this.baseRepository = new BaseRepository(context);
- this.headerHorizontalPadding = DimensionUtil.INSTANCE.dpToPx(context, R.dimen.spacer_1hx);
- this.headerVerticalPaddingNth = DimensionUtil.INSTANCE.dpToPx(context, R.dimen.spacer_2x);
+
+ final var resources = context.getResources();
+ this.headerHorizontalPadding = resources.getDimensionPixelSize(R.dimen.spacer_1hx);
+ this.headerVerticalPaddingNth = resources.getDimensionPixelSize(R.dimen.spacer_2x);
}
@Override
diff --git a/app/src/main/res/animator/appbar_elevation_off.xml b/app/src/main/res/animator/appbar_elevation_off.xml
deleted file mode 100644
index d24dcb340..000000000
--- a/app/src/main/res/animator/appbar_elevation_off.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item>
- <objectAnimator
- android:propertyName="elevation"
- android:valueTo="0dp"
- android:valueType="floatType" />
- </item>
-</selector>
diff --git a/app/src/main/res/animator/appbar_elevation_on.xml b/app/src/main/res/animator/appbar_elevation_on.xml
deleted file mode 100644
index 6bd52cf3b..000000000
--- a/app/src/main/res/animator/appbar_elevation_on.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- tools:ignore="PrivateResource">
- <item>
- <objectAnimator
- android:propertyName="elevation"
- android:valueTo="@dimen/design_appbar_elevation"
- android:valueType="floatType" />
- </item>
-</selector>
diff --git a/app/src/main/res/drawable-hdpi/ic_splash_screen.png b/app/src/main/res/drawable-hdpi/ic_splash_screen.png
deleted file mode 100644
index 070efc396..000000000
--- a/app/src/main/res/drawable-hdpi/ic_splash_screen.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_splash_screen.png b/app/src/main/res/drawable-mdpi/ic_splash_screen.png
deleted file mode 100644
index 0a3717448..000000000
--- a/app/src/main/res/drawable-mdpi/ic_splash_screen.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_splash_screen.png b/app/src/main/res/drawable-xhdpi/ic_splash_screen.png
deleted file mode 100644
index bfe6dca49..000000000
--- a/app/src/main/res/drawable-xhdpi/ic_splash_screen.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_splash_screen.png b/app/src/main/res/drawable-xxhdpi/ic_splash_screen.png
deleted file mode 100644
index c34788f0e..000000000
--- a/app/src/main/res/drawable-xxhdpi/ic_splash_screen.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_splash_screen.png b/app/src/main/res/drawable-xxxhdpi/ic_splash_screen.png
deleted file mode 100644
index 32c45e466..000000000
--- a/app/src/main/res/drawable-xxxhdpi/ic_splash_screen.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable/bottom_sheet_rounded.xml b/app/src/main/res/drawable/bottom_sheet_rounded.xml
deleted file mode 100644
index ba266ed32..000000000
--- a/app/src/main/res/drawable/bottom_sheet_rounded.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="?attr/colorSurface" />
- <corners
- android:topLeftRadius="16dp"
- android:topRightRadius="16dp" />
-
-</shape> \ No newline at end of file
diff --git a/app/src/main/res/drawable/circle.xml b/app/src/main/res/drawable/circle.xml
deleted file mode 100644
index 8a1da5d66..000000000
--- a/app/src/main/res/drawable/circle.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="ring"
- android:innerRadiusRatio="2.5"
- android:thickness="4dp"
- android:useLevel="true">
- <solid android:color="@color/defaultBrand" />
-</shape> \ 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 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/due_overdue" />
-
- <corners
- android:radius="4dp" />
-</shape> \ 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 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/due_today" />
-
- <corners
- android:radius="4dp" />
-</shape> \ No newline at end of file
diff --git a/app/src/main/res/drawable/due_tomorrow_background.xml b/app/src/main/res/drawable/due_tomorrow_background.xml
deleted file mode 100644
index a986c42e2..000000000
--- a/app/src/main/res/drawable/due_tomorrow_background.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/due_tomorrow" />
-
- <corners
- android:radius="4dp" />
-</shape> \ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_check_box_24.xml b/app/src/main/res/drawable/ic_check_box_24.xml
new file mode 100644
index 000000000..0c3970b1a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_check_box_24.xml
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+ android:tint="#757575" android:viewportHeight="24"
+ android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_check_circle_24.xml b/app/src/main/res/drawable/ic_check_circle_24.xml
new file mode 100644
index 000000000..45c61fa3f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_check_circle_24.xml
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+ android:tint="?attr/colorOnSurface" android:viewportHeight="24"
+ android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_format_paint_grey600_24dp.xml b/app/src/main/res/drawable/ic_format_paint_grey600_24dp.xml
deleted file mode 100644
index a2308a55f..000000000
--- a/app/src/main/res/drawable/ic_format_paint_grey600_24dp.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<vector android:autoMirrored="true" android:height="24dp"
- android:tint="#757575" android:viewportHeight="24.0"
- android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#FF000000" android:pathData="M18,4V3c0,-0.55 -0.45,-1 -1,-1H5c-0.55,0 -1,0.45 -1,1v4c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1V6h1v4H9v11c0,0.55 0.45,1 1,1h2c0.55,0 1,-0.45 1,-1v-9h8V4h-3z"/>
-</vector>
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 @@
+<vector android:autoMirrored="true" android:height="24dp"
+ android:tint="?attr/colorOnSurface" android:viewportHeight="24"
+ android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"/>
+ <path android:fillColor="@android:color/white" android:pathData="M12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
+</vector>
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 @@
+<vector android:autoMirrored="true" android:height="24dp"
+ android:tint="?attr/colorOnSurface" android:viewportHeight="24"
+ android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@android:color/white" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM15.29,16.71L11,12.41V7h2v4.59l3.71,3.71L15.29,16.71z"/>
+</vector>
diff --git a/app/src/main/res/drawable/splash_screen.xml b/app/src/main/res/drawable/splash_screen.xml
deleted file mode 100644
index d22531b3f..000000000
--- a/app/src/main/res/drawable/splash_screen.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item android:drawable="@color/defaultBrand" />
-
- <item>
- <bitmap
- android:gravity="center"
- android:src="@drawable/ic_splash_screen" />
- </item>
-
-</layer-list> \ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_filter.xml b/app/src/main/res/layout/dialog_filter.xml
index b95c2b0c8..2b1e3499c 100644
--- a/app/src/main/res/layout/dialog_filter.xml
+++ b/app/src/main/res/layout/dialog_filter.xml
@@ -11,7 +11,7 @@
android:layout_height="wrap_content"
android:background="@null"
app:tabInlineLabel="true"
- app:tabMode="fixed"
+ app:tabMode="auto"
app:tabUnboundedRipple="true" />
<androidx.viewpager2.widget.ViewPager2
diff --git a/app/src/main/res/layout/dialog_filter_done.xml b/app/src/main/res/layout/dialog_filter_done.xml
new file mode 100644
index 000000000..5cf3fedb0
--- /dev/null
+++ b/app/src/main/res/layout/dialog_filter_done.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.recyclerview.widget.RecyclerView 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:id="@+id/doneType"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="?attr/dialogPreferredPadding"
+ app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+ tools:listitem="@layout/item_filter_duetype" /> \ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_card_edit_tab_details.xml b/app/src/main/res/layout/fragment_card_edit_tab_details.xml
index 631bc342f..c39a00fc5 100644
--- a/app/src/main/res/layout/fragment_card_edit_tab_details.xml
+++ b/app/src/main/res/layout/fragment_card_edit_tab_details.xml
@@ -69,81 +69,22 @@
android:layout_marginTop="@dimen/spacer_1x"
android:layout_marginBottom="@dimen/spacer_1hx"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
- app:layout_constraintBottom_toTopOf="@id/dueDateDateWrapper"
+ app:layout_constraintBottom_toTopOf="@id/cardDueDateView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/peopleWrapper"
tools:listitem="@tools:sample/avatars" />
- <com.google.android.material.textfield.TextInputLayout
- android:id="@+id/dueDateDateWrapper"
- android:layout_width="0dp"
+ <it.niedermann.nextcloud.deck.ui.card.details.CardDueDateView
+ android:id="@+id/cardDueDateView"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacer_2x"
- android:layout_marginEnd="@dimen/spacer_2x"
- android:hint="@string/hint_due_date_date"
- android:labelFor="@id/dueDateDate"
app:layout_constraintBottom_toTopOf="@id/descriptionWrapper"
- app:layout_constraintEnd_toStartOf="@id/dueDateTimeWrapper"
- app:layout_constraintHorizontal_weight="2"
+ app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/assignees"
- app:startIconDrawable="@drawable/calendar_blank_grey600_24dp">
-
- <EditText
- android:id="@+id/dueDateDate"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:enabled="true"
- android:focusable="false"
- android:importantForAutofill="no"
- android:inputType="date"
- android:maxLines="1"
- tools:text="01/07/2020" />
- </com.google.android.material.textfield.TextInputLayout>
+ app:layout_constraintTop_toBottomOf="@id/assignees" />
- <com.google.android.material.textfield.TextInputLayout
- android:id="@+id/dueDateTimeWrapper"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/spacer_1hx"
- android:hint="@string/hint_due_date_time"
- android:labelFor="@id/dueDateTime"
- app:layout_constraintBottom_toBottomOf="@id/dueDateDateWrapper"
- app:layout_constraintEnd_toStartOf="@id/clearDueDate"
- app:layout_constraintHorizontal_weight="1"
- app:layout_constraintStart_toEndOf="@id/dueDateDateWrapper"
- app:layout_constraintTop_toTopOf="@id/dueDateDateWrapper">
-
- <EditText
- android:id="@+id/dueDateTime"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:enabled="true"
- android:focusable="false"
- android:importantForAutofill="no"
- android:inputType="datetime"
- android:maxLines="1"
- android:minLines="0"
- android:textAlignment="center"
- tools:text="11:45" />
- </com.google.android.material.textfield.TextInputLayout>
-
- <ImageView
- android:id="@+id/clearDueDate"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginVertical="@dimen/spacer_1hx"
- android:layout_marginStart="@dimen/spacer_1x"
- android:layout_marginEnd="0dp"
- android:contentDescription="@string/label_clear_due_date"
- android:padding="@dimen/spacer_11qx"
- android:translationY="@dimen/spacer_1hx"
- app:layout_constraintBottom_toBottomOf="@id/dueDateTimeWrapper"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toEndOf="@id/dueDateTimeWrapper"
- app:layout_constraintTop_toTopOf="@id/dueDateTimeWrapper"
- app:srcCompat="@drawable/ic_close_circle_grey600" />
<RelativeLayout
android:id="@+id/descriptionWrapper"
@@ -153,7 +94,7 @@
app:layout_constraintBottom_toTopOf="@id/projectsTitle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/dueDateDateWrapper">
+ app:layout_constraintTop_toBottomOf="@id/cardDueDateView">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/descriptionEditorWrapper"
diff --git a/app/src/main/res/layout/item_card_compact.xml b/app/src/main/res/layout/item_card_compact.xml
index 3a14b0d43..75d95f796 100644
--- a/app/src/main/res/layout/item_card_compact.xml
+++ b/app/src/main/res/layout/item_card_compact.xml
@@ -52,15 +52,12 @@
app:srcCompat="@drawable/ic_sync_blue_24dp"
tools:visibility="visible" />
- <com.google.android.material.textview.MaterialTextView
+ <it.niedermann.nextcloud.deck.ui.view.DueDateChip
android:id="@+id/card_due_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:drawablePadding="@dimen/spacer_1hx"
- android:gravity="center"
- android:paddingHorizontal="@dimen/spacer_1x"
- android:paddingVertical="@dimen/spacer_1hx"
- app:drawableStartCompat="@drawable/calendar_blank_grey600_24dp"
+ app:compactMode="true"
+ tools:chipIcon="@drawable/ic_time_24"
tools:text="tomorrow" />
<ImageView
diff --git a/app/src/main/res/layout/item_card_default.xml b/app/src/main/res/layout/item_card_default.xml
index 7454129f4..3dfcff46e 100644
--- a/app/src/main/res/layout/item_card_default.xml
+++ b/app/src/main/res/layout/item_card_default.xml
@@ -54,15 +54,11 @@
app:srcCompat="@drawable/ic_sync_blue_24dp"
tools:visibility="visible" />
- <androidx.appcompat.widget.AppCompatTextView
+ <it.niedermann.nextcloud.deck.ui.view.DueDateChip
android:id="@+id/card_due_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:drawablePadding="@dimen/spacer_1hx"
- android:gravity="center"
- android:paddingHorizontal="@dimen/spacer_1x"
- android:paddingVertical="@dimen/spacer_1hx"
- app:drawableStartCompat="@drawable/calendar_blank_grey600_24dp"
+ tools:chipIcon="@drawable/ic_time_24"
tools:text="tomorrow" />
</LinearLayout>
@@ -103,9 +99,10 @@
android:id="@+id/card_count_tasks"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:drawablePadding="@dimen/spacer_1qx"
android:gravity="center_vertical"
android:padding="@dimen/spacer_1hx"
- tools:drawableStartCompat="@drawable/ic_check_grey600_24dp"
+ tools:drawableStartCompat="@drawable/ic_check_box_24"
tools:text="1/2" />
<com.google.android.material.textview.MaterialTextView
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" />
- <com.google.android.material.textview.MaterialTextView
+ <it.niedermann.nextcloud.deck.ui.view.DueDateChip
android:id="@+id/card_due_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:drawablePadding="@dimen/spacer_1hx"
- android:gravity="center"
- android:paddingHorizontal="@dimen/spacer_1x"
- android:paddingVertical="@dimen/spacer_1hx"
- app:drawableStartCompat="@drawable/calendar_blank_grey600_24dp"
+ tools:chipIcon="@drawable/ic_time_24"
tools:text="tomorrow" />
<ImageView
diff --git a/app/src/main/res/layout/item_filter_donetype.xml b/app/src/main/res/layout/item_filter_donetype.xml
new file mode 100644
index 000000000..9cf823c77
--- /dev/null
+++ b/app/src/main/res/layout/item_filter_donetype.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.google.android.flexbox.FlexboxLayout 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="wrap_content"
+ android:background="?attr/selectableItemBackground"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/doneType"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="middle"
+ android:padding="@dimen/spacer_2x"
+ android:textAppearance="?attr/textAppearanceListItem"
+ tools:text="@tools:sample/lorem" />
+
+ <androidx.appcompat.widget.AppCompatImageView
+ android:id="@+id/selected_check"
+ android:layout_width="22dp"
+ android:layout_height="22dp"
+ android:layout_marginStart="@dimen/spacer_1x"
+ app:layout_alignSelf="center"
+ app:layout_flexShrink="0"
+ app:srcCompat="@drawable/selected_check"
+ tools:src="@drawable/ic_check_grey600_24dp" />
+
+</com.google.android.flexbox.FlexboxLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/view_card_due_date.xml b/app/src/main/res/layout/view_card_due_date.xml
new file mode 100644
index 000000000..77398f5b1
--- /dev/null
+++ b/app/src/main/res/layout/view_card_due_date.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content">
+
+ <ImageView
+ android:id="@+id/doneCheck"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/spacer_1qx"
+ android:layout_marginEnd="0dp"
+ android:layout_marginBottom="@dimen/spacer_1hx"
+ android:contentDescription="@null"
+ android:padding="@dimen/spacer_11qx"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:srcCompat="@drawable/ic_check_white_24dp"
+ app:tint="?attr/colorOnSurface"
+ tools:visibility="gone" />
+
+ <TextView
+ android:id="@+id/doneDate"
+ style="?attr/textAppearanceBody1"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ app:layout_constraintBottom_toBottomOf="@id/doneCheck"
+ app:layout_constraintEnd_toStartOf="@id/clearDone"
+ app:layout_constraintStart_toEndOf="@id/doneCheck"
+ app:layout_constraintTop_toTopOf="@id/doneCheck"
+ tools:text="@tools:sample/date/ddmmyy"
+ tools:visibility="gone" />
+
+ <TextView
+ android:id="@+id/done_due_date"
+ style="?attr/textAppearanceBody1"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/spacer_1x"
+ app:layout_constraintEnd_toStartOf="@id/clearDone"
+ app:layout_constraintStart_toEndOf="@id/doneCheck"
+ app:layout_constraintTop_toBottomOf="@id/doneDate"
+ tools:text="@tools:sample/date/ddmmyy"
+ tools:visibility="gone" />
+
+ <ImageView
+ android:id="@+id/clearDone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginVertical="@dimen/spacer_1hx"
+ android:layout_marginStart="@dimen/spacer_1x"
+ android:layout_marginEnd="0dp"
+ android:contentDescription="@string/label_clear_done"
+ android:padding="@dimen/spacer_11qx"
+ app:layout_constraintBottom_toBottomOf="@id/doneDate"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="@id/doneDate"
+ app:srcCompat="@drawable/ic_close_circle_grey600"
+ tools:visibility="gone" />
+
+ <com.google.android.material.textfield.TextInputLayout
+ android:id="@+id/dueDateDateWrapper"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/spacer_2x"
+ android:hint="@string/hint_due_date_date"
+ android:labelFor="@id/dueDateDate"
+ app:layout_constraintBottom_toTopOf="@id/markAsDone"
+ app:layout_constraintEnd_toStartOf="@id/dueDateTimeWrapper"
+ app:layout_constraintHorizontal_weight="2"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/done_due_date"
+ app:startIconDrawable="@drawable/calendar_blank_grey600_24dp">
+
+ <EditText
+ android:id="@+id/dueDateDate"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:enabled="true"
+ android:focusable="false"
+ android:importantForAutofill="no"
+ android:inputType="date"
+ android:maxLines="1"
+ tools:text="01/07/2020" />
+ </com.google.android.material.textfield.TextInputLayout>
+
+ <com.google.android.material.textfield.TextInputLayout
+ android:id="@+id/dueDateTimeWrapper"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/spacer_1hx"
+ android:hint="@string/hint_due_date_time"
+ android:labelFor="@id/dueDateTime"
+ app:layout_constraintBottom_toBottomOf="@id/dueDateDateWrapper"
+ app:layout_constraintEnd_toStartOf="@id/clearDueDate"
+ app:layout_constraintHorizontal_weight="1"
+ app:layout_constraintStart_toEndOf="@id/dueDateDateWrapper"
+ app:layout_constraintTop_toTopOf="@id/dueDateDateWrapper">
+
+ <EditText
+ android:id="@+id/dueDateTime"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:enabled="true"
+ android:focusable="false"
+ android:importantForAutofill="no"
+ android:inputType="datetime"
+ android:maxLines="1"
+ android:minLines="0"
+ android:textAlignment="center"
+ tools:text="11:45" />
+ </com.google.android.material.textfield.TextInputLayout>
+
+ <ImageView
+ android:id="@+id/clearDueDate"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginVertical="@dimen/spacer_1hx"
+ android:layout_marginStart="@dimen/spacer_1x"
+ android:layout_marginEnd="0dp"
+ android:contentDescription="@string/label_clear_due_date"
+ android:padding="@dimen/spacer_11qx"
+ android:translationY="@dimen/spacer_1hx"
+ app:layout_constraintBottom_toBottomOf="@id/dueDateTimeWrapper"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toEndOf="@id/dueDateTimeWrapper"
+ app:layout_constraintTop_toTopOf="@id/dueDateTimeWrapper"
+ app:srcCompat="@drawable/ic_close_circle_grey600" />
+
+ <com.google.android.material.button.MaterialButton
+ android:id="@+id/markAsDone"
+ style="@style/Widget.Material3.Button"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/spacer_2x"
+ android:layout_marginBottom="@dimen/spacer_1hx"
+ android:text="@string/simple_completed"
+ app:backgroundTint="@color/defaultBrand"
+ app:icon="@drawable/ic_check_white_24dp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/dueDateDateWrapper" />
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/layout/widget_single_card.xml b/app/src/main/res/layout/widget_single_card.xml
index 5646b98f1..b868a59d5 100644
--- a/app/src/main/res/layout/widget_single_card.xml
+++ b/app/src/main/res/layout/widget_single_card.xml
@@ -39,7 +39,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@null"
- tools:src="@drawable/calendar_blank_grey600_24dp" />
+ tools:src="@drawable/ic_time_24" />
<TextView
android:id="@+id/card_due_date"
diff --git a/app/src/main/res/menu/archived_card_menu.xml b/app/src/main/res/menu/archived_card_menu.xml
deleted file mode 100644
index 12448e691..000000000
--- a/app/src/main/res/menu/archived_card_menu.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
- <item
- android:id="@+id/action_card_dearchive"
- android:title="@string/action_card_dearchive"
- app:showAsAction="never" />
-
- <item
- android:id="@+id/action_card_delete"
- android:title="@string/action_card_delete"
- app:showAsAction="never" />
-</menu>
diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml
index 3e9f08068..7eff416c2 100644
--- a/app/src/main/res/values-ar/strings.xml
+++ b/app/src/main/res/values-ar/strings.xml
@@ -268,6 +268,7 @@
<string name="manage_list">إدارة القائمة </string>
<string name="simple_reply">رد</string>
<string name="append_text_to_description">إلحاق بالوصف </string>
+ <string name="append_text_as_task">إلحاق بالوصف كمُهمة</string>
<string name="add_text_as_comment">أضف كتعليق</string>
<string name="progress_count">%1$d من %2$d</string>
<plurals name="progress_error_count">
diff --git a/app/src/main/res/values-b+en+001/strings.xml b/app/src/main/res/values-b+en+001/strings.xml
index 42429e20b..9f4290cd8 100644
--- a/app/src/main/res/values-b+en+001/strings.xml
+++ b/app/src/main/res/values-b+en+001/strings.xml
@@ -260,6 +260,7 @@
<string name="manage_list">Manage list</string>
<string name="simple_reply">Reply</string>
<string name="append_text_to_description">Append to description</string>
+ <string name="append_text_as_task">Append to description as task</string>
<string name="add_text_as_comment">Add as comment</string>
<string name="progress_count">%1$d of %2$d</string>
<plurals name="progress_error_count">
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index fd0ca7c55..5de3c231a 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -260,6 +260,7 @@
<string name="manage_list">Liste verwalten</string>
<string name="simple_reply">Antworten</string>
<string name="append_text_to_description">An Beschreibung anhängen</string>
+ <string name="append_text_as_task">Als Aufgabe an Beschreibung anhängen</string>
<string name="add_text_as_comment">Als Kommentar hinzufügen</string>
<string name="progress_count">%1$d von %2$d</string>
<plurals name="progress_error_count">
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 29de8ad78..ce08f5ea0 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -262,6 +262,7 @@
<string name="manage_list">Administrar su lista</string>
<string name="simple_reply">Responder</string>
<string name="append_text_to_description">Añadir a la descripción</string>
+ <string name="append_text_as_task">Añadir a la descripción como tarea</string>
<string name="add_text_as_comment">Añadir como comentario</string>
<string name="progress_count">%1$d de %2$d</string>
<plurals name="progress_error_count">
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 79c9785d5..680e4e4ae 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -158,6 +158,7 @@
<string name="title_is_mandatory">Il titolo è richiesto</string>
<string name="provide_at_least_a_title_or_description">Fornisci almeno un titolo e una descrizione</string>
<string name="welcome_text">Benvenuto in %1$s</string>
+ <string name="welcome_text_further_accounts">Aggiungi un altro account</string>
<string name="maintenance_mode_explanation">Il server %1$s attualmente è in manutenzione. Contatta l\'amministratore o riprova più tardi.</string>
<string name="share_add_to_card">Aggiungi a scheda</string>
<string name="share_success">Aggiunto %1$s a %2$s correttamente</string>
@@ -261,6 +262,7 @@
<string name="manage_list">Gestisci elenco</string>
<string name="simple_reply">Rispondi</string>
<string name="append_text_to_description">Aggiungi alla descrizione</string>
+ <string name="append_text_as_task">Accoda alla descrizione come attività</string>
<string name="add_text_as_comment">Aggiungi come commento</string>
<string name="progress_count">%1$d di %2$d</string>
<plurals name="progress_error_count">
@@ -336,5 +338,8 @@
<string name="card_outdated">Il contenuto di questa scheda potrebbe essere obsoleto.</string>
<string name="show_error">Mostra errore</string>
<string name="push_notification_link_empty">A causa di un problema noto nella web app di Deck, sfortunatamente non possiamo mostrare questa scheda. Per altre informazioni vedi: %1$s</string>
+ <string name="enter_search_term_title">Inserisci termine di ricerca</string>
+ <string name="enter_search_term_description">Inserisci il termine di ricerca per trovare schede in questa lavagna</string>
<string name="no_search_results_title">Nessun risultato di ricerca</string>
- </resources>
+ <string name="no_search_results_description">Non abbiamo trovato alcun risultato per il termine di ricerca scelto</string>
+</resources>
diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml
index b59427909..b301f9652 100644
--- a/app/src/main/res/values-nb-rNO/strings.xml
+++ b/app/src/main/res/values-nb-rNO/strings.xml
@@ -260,6 +260,7 @@
<string name="manage_list">Håndtere liste</string>
<string name="simple_reply">Svar</string>
<string name="append_text_to_description">Legg til beskrivelsen</string>
+ <string name="append_text_as_task">Legg til beskrivelse som oppgave</string>
<string name="add_text_as_comment">Legg til som kommentar</string>
<string name="progress_count">%1$d av %2$d</string>
<plurals name="progress_error_count">
diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml
index d3e6cb425..81e38f628 100644
--- a/app/src/main/res/values-night/colors.xml
+++ b/app/src/main/res/values-night/colors.xml
@@ -34,10 +34,10 @@
<!-- ======================================= -->
<!-- Due Date badges -->
- <color name="due_tomorrow">#232323</color>
- <color name="due_today">#ac7c06</color>
- <color name="due_overdue">#aa2926</color>
- <color name="due_text_tomorrow">#ffffff</color>
- <color name="due_text_today">#ffffff</color>
- <color name="due_text_overdue">#ffffff</color>
+ <color name="due_today">#19c28900</color>
+ <color name="due_overdue">#19ee312b</color>
+ <color name="due_done">#1936914e</color>
+ <color name="due_text_today">#c28900</color>
+ <color name="due_text_overdue">#f36864</color>
+ <color name="due_text_done">#3ea75a</color>
</resources>
diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml
index 5b1719cb3..35e6fe1c6 100644
--- a/app/src/main/res/values-sr/strings.xml
+++ b/app/src/main/res/values-sr/strings.xml
@@ -262,6 +262,7 @@
<string name="manage_list">Управљај списком</string>
<string name="simple_reply">Одговори</string>
<string name="append_text_to_description">Придодај на опис</string>
+ <string name="append_text_as_task">Надовежи опису као задатак</string>
<string name="add_text_as_comment">Додај као коментар</string>
<string name="progress_count">%1$d од %2$d</string>
<plurals name="progress_error_count">
diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml
index e080853cd..488f44679 100644
--- a/app/src/main/res/values-sv/strings.xml
+++ b/app/src/main/res/values-sv/strings.xml
@@ -260,6 +260,7 @@
<string name="manage_list">Hantera lista</string>
<string name="simple_reply">Svara</string>
<string name="append_text_to_description">Lägg till beskrivning</string>
+ <string name="append_text_as_task">Lägg till i beskrivningen som uppgift</string>
<string name="add_text_as_comment">Lägg till som kommentar</string>
<string name="progress_count">%1$d av %2$d</string>
<plurals name="progress_error_count">
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index 553f877cb..3335a9f43 100644
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -258,6 +258,7 @@
<string name="manage_list">管理清單</string>
<string name="simple_reply">回覆</string>
<string name="append_text_to_description">附加到描述</string>
+ <string name="append_text_as_task">附加到描述作為任務</string>
<string name="add_text_as_comment">新增為留言</string>
<string name="progress_count">%1$d 之 %2$d</string>
<plurals name="progress_error_count">
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 0ebb20c27..8ccf1db22 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -258,6 +258,7 @@
<string name="manage_list">管理清單</string>
<string name="simple_reply">回覆</string>
<string name="append_text_to_description">附加到描述</string>
+ <string name="append_text_as_task">附加到描述作為工作項目</string>
<string name="add_text_as_comment">新增為留言</string>
<string name="progress_count">%1$d 之 %2$d</string>
<plurals name="progress_error_count">
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index 715f8b814..8e70e68ea 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -8,4 +8,7 @@
<attr name="description" format="string" />
<attr name="image" format="reference" />
</declare-styleable>
+ <declare-styleable name="DueDateChip">
+ <attr name="compactMode" format="boolean" />
+ </declare-styleable>
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index c6536b902..1b9a313f4 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -38,12 +38,12 @@
<!-- ======================================= -->
<!-- Due Date badges -->
- <color name="due_tomorrow">#f2f2f2</color>
- <color name="due_today">#f1c14b</color>
- <color name="due_overdue">#ef6e6b</color>
- <color name="due_text_tomorrow">#666666</color>
- <color name="due_text_today">#333333</color>
- <color name="due_text_overdue">#ffffff</color>
+ <color name="due_today">#f8f2e5</color>
+ <color name="due_overdue">#fbe7e6</color>
+ <color name="due_done">#e9f1eb</color>
+ <color name="due_text_today">#855d00</color>
+ <color name="due_text_overdue">#c61610</color>
+ <color name="due_text_done">#286c39</color>
<!-- Activity -->
<color name="activity_create">#00D400</color>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c6eca37fa..4b59ce20d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -5,7 +5,6 @@
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="hint_search_deck">Search deck</string>
- <string name="simple_boards">Boards</string>
<string name="simple_add">Add</string>
<string name="simple_save">Save</string>
<string name="simple_more">More</string>
@@ -16,11 +15,9 @@
<string name="simple_error">Error</string>
<string name="simple_exception">Exception</string>
<string name="simple_close">Close</string>
- <string name="simple_open">Open</string>
- <string name="simple_switch">Switch</string>
<string name="simple_filter">Filter</string>
- <string name="simple_overdue">Overdue</string>
- <string name="simple_clear">Clear</string>
+ <string name="simple_completed">Completed</string>
+ <string name="simple_reset">Reset</string>
<string name="simple_discard">Discard</string>
<string name="simple_update">Update</string>
<string name="simple_delete">Delete</string>
@@ -32,7 +29,6 @@
<string name="simple_select">Select</string>
<string name="simple_comment">Comment</string>
<string name="simple_disabled">disabled</string>
- <string name="simple_copied">Copied</string>
<string name="simple_archive">Archive</string>
<string name="simple_unassigned">Unassigned</string>
<string name="hint_error_appeared">An error appeared</string>
@@ -97,6 +93,8 @@
<string name="add_board">Add board</string>
<string name="label_clear_due_date">Clear due date</string>
+ <string name="label_clear_done">Not completed</string>
+ <string name="label_due_at">Due at: %1$s</string>
<string name="label_add">Add %1$s</string>
<string name="url_maintainer" translatable="false">https://www.niedermann.it/</string>
@@ -112,6 +110,7 @@
<string name="url_fragment_server_logs" translatable="false">/index.php/settings/admin/logging</string>
<string name="url_fragment_share_card_pre_1_0_0" translatable="false">/index.php/apps/deck/#!/board/%1$d/card/%2$d</string>
<string name="url_fragment_share_card_since_1_0_0" translatable="false">/index.php/apps/deck/#/board/%1$d/card/%2$d</string>
+ <string name="url_fragment_share_card_since_1_12_0" translatable="false">/index.php/apps/deck/board/%1$d/card/%2$d</string>
<string name="card_edit_details">Details</string>
<string name="card_edit_attachments">Attachments</string>
@@ -120,9 +119,7 @@
<string name="no_files_attached_to_this_card">There are no files attached to this card.</string>
<string name="attachments">Attachments</string>
<string name="no_cards">No cards yet</string>
- <string name="no_account">No account configured</string>
<string name="account_already_added">The account %1$s has already been added</string>
- <string name="account_is_getting_imported">Account is getting imported</string>
<string name="not_synced_yet">Not synced yet</string>
<string name="no_lists_yet">No lists yet</string>
<string name="do_you_want_to_save_your_changes">Do you want to save your changes?</string>
@@ -138,11 +135,9 @@
</plurals>
<string name="add_a_new_list_using_the_button">Add a new list using the + button</string>
<string name="add_a_new_card_using_the_button">Add a new card using the + button</string>
- <string name="update_deck">Update Deck web app</string>
<string name="deck_outdated_please_update">Your Deck web app version is too old (%1$s). Please update to use this Android app as client.</string>
<string name="delete_board_message">This will permanently delete this board including all lists and cards.</string>
<string name="settings_theme_title">Theme</string>
- <string name="settings_branding_title">Branding</string>
<string name="settings_compact_title">Compact mode</string>
<string name="settings_cover_images_title">Cover images</string>
<string name="settings_debugging">Debug logs</string>
@@ -178,7 +173,6 @@
<string name="provide_at_least_a_title_or_description">Provide at least a title or description</string>
<string name="welcome_text">Welcome to %1$s</string>
<string name="welcome_text_further_accounts">Add another account</string>
- <string name="maintenance_mode_explanation">The server %1$s is currently in maintenance mode. Please contact your administrator or try later again.</string>
<string name="share_add_to_card">Add to card</string>
<string name="share_success">Successfully added %1$s to %2$s</string>
<string name="add_comment">Add comment</string>
@@ -187,7 +181,6 @@
<string name="no_boards">No boards yet</string>
<string name="add_a_new_board_using_the_button">Add a new board using the + button</string>
<string name="choose_board">Choose board</string>
- <string name="choose_list">Choose list</string>
<string name="task_count">%1$s/%2$s</string>
<string name="open_in_browser">Open in browser</string>
<string name="updating_card">Updating card…</string>
@@ -203,13 +196,12 @@
<string name="filter_month">Next 30 days</string>
<string name="filter_no_due">No due date</string>
<string name="filter_later">Later</string>
- <string name="filter_by_tag">Filter by tag</string>
- <string name="filter_by_assigned_user">Filter by assigned user</string>
- <string name="filter_by_duedate">Filter by due date</string>
+
+ <string name="filter_done_no_filter">All</string>
+ <string name="filter_done_done">Completed</string>
+ <string name="filter_done_undone">Not completed</string>
<string name="archived_cards">Archived cards</string>
- <string name="action_card_dearchive">Undo card archiving</string>
- <string name="action_archived_cards">Browse archived cards</string>
<string name="attachment_already_exists">Attachment already exists</string>
<string name="pick_custom_color">Pick custom color</string>
<string name="manage_tags">Manage tags</string>
@@ -220,6 +212,7 @@
<string name="filter_tags_title">Tags</string>
<string name="filter_user_title">Users</string>
<string name="filter_duedate_title">Due date</string>
+ <string name="filter_done_title">Completed</string>
<string name="action_board_dearchive">Undo board archiving</string>
<string name="archived_boards">Archived boards</string>
@@ -230,7 +223,6 @@
<string name="error_revoking_ac">Error while revoking the access for %1$s</string>
<string name="error_create_label">Error while creating label %1$s</string>
<string name="maintenance_mode">Server is in maintenance mode</string>
- <string name="server_error">Server error</string>
<string name="error_edit_activity_killed_by_android">Android finished the edit mode because it needed more system resources for other apps.</string>
<string name="error_dialog_title">Oh no - What now? 🙁</string>
@@ -298,10 +290,8 @@
<string name="card_does_not_yet_exist">Card does not yet exist in Deck</string>
<string name="widget_stack_title">List</string>
- <string name="widget_filter_title">Filter</string>
<string name="widget_stack_header_icon">Widget header icon</string>
<string name="widget_placeholder_icon">Widget placeholder icon</string>
- <string name="select_stack">Select list</string>
<string name="project_type_deck_board">Deck board</string>
<string name="project_type_deck_card">Deck card</string>
<string name="project_type_file">File</string>
@@ -319,9 +309,6 @@
<string name="simple_clone">Clone</string>
<string name="user_avatar">User avatar</string>
<string name="simple_unassign">Unassign</string>
- <string name="simple_contact">Contact</string>
- <string name="simple_file">File</string>
- <string name="simple_camera">Camera</string>
<string name="take_photo">Take a photo</string>
<string name="take_photo_switch_camera">Switch camera</string>
<string name="take_photo_toggle_torch">Toggle torch</string>