diff options
author | Stefan Niedermann <info@niedermann.it> | 2020-12-09 14:14:47 +0300 |
---|---|---|
committer | Stefan Niedermann <info@niedermann.it> | 2020-12-09 14:14:47 +0300 |
commit | 7c5b734d5a17188f23ae8ba5068887348e446365 (patch) | |
tree | 379e1904e0a170947941ac1cd7a0678241858723 /app | |
parent | 8337afa248e314732775833b05096835173af40b (diff) | |
parent | 61506f9d29daf0559fa12c70a25a45a4c6d83fa1 (diff) |
Merge branch 'master' into 597-filter-widget
# Conflicts:
# app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java
# app/src/main/res/values/strings.xml
Diffstat (limited to 'app')
68 files changed, 732 insertions, 433 deletions
diff --git a/app/build.gradle b/app/build.gradle index 551321b6e..252da7a00 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "it.niedermann.nextcloud.deck" minSdkVersion 19 targetSdkVersion 29 - versionCode 1012001 - versionName "1.12.1" + versionCode 1013000 + versionName "1.13.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true javaCompileOptions { @@ -104,8 +104,6 @@ dependencies { // --- Backend-Libraries --- // ------------------------- - implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.4.10' - // Room components implementation "androidx.room:room-runtime:$rootProject.roomVersion" annotationProcessor "androidx.room:room-compiler:$rootProject.roomVersion" diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/util/AttachmentUtilTest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/util/AttachmentUtilTest.java new file mode 100644 index 000000000..a72f74ec1 --- /dev/null +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/util/AttachmentUtilTest.java @@ -0,0 +1,50 @@ +package it.niedermann.nextcloud.deck.util; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import it.niedermann.nextcloud.deck.model.Attachment; +import it.niedermann.nextcloud.deck.model.ocs.Version; + +import static org.junit.Assert.assertEquals; + +@RunWith(AndroidJUnit4.class) +public class AttachmentUtilTest { + + @Test + public void testGetThumbnailUrl() { + final Version versionThatDoesSupportFileAttachments = new Version("1.3.0", 1, 3, 0); + final Version versionThatDoesNotSupportFileAttachments = new Version("1.2.0", 1, 2, 0); + final String accountUrl = "https://example.com"; + + // TODO depends on https://github.com/nextcloud/deck/pull/2638 +// final Attachment attachment1 = new Attachment(); +// attachment1.setFileId("1337"); +// final String thumbnailUrl1 = AttachmentUtil.getThumbnailUrl(versionThatDoesSupportFileAttachments, accountUrl, -1L, attachment1, 500); +// assertEquals("https://example.com/index.php/core/preview?fileId=1337&x=500&y=500", thumbnailUrl1); +// +// final Attachment attachment2 = new Attachment(); +// attachment2.setFileId("0815"); +// final String thumbnailUrl2 = AttachmentUtil.getThumbnailUrl(versionThatDoesSupportFileAttachments, accountUrl, 0L, attachment2, 4711); +// assertEquals("https://example.com/index.php/core/preview?fileId=0815&x=4711&y=4711", thumbnailUrl2); + + // Given there is an invalid fileId... + final Attachment attachment3 = new Attachment(); + attachment3.setId(999L); + attachment3.setFileId(""); + final String thumbnailUrl3 = AttachmentUtil.getThumbnailUrl(versionThatDoesSupportFileAttachments, accountUrl, 15L, attachment3, 205); + // ... a fallback to the attachment itself should be returned + assertEquals("https://example.com/index.php/apps/deck/cards/15/attachment/999", thumbnailUrl3); + + // Given the server version does not support file attachments yet... + final Attachment attachment4 = new Attachment(); + attachment4.setId(111L); + attachment4.setFileId("222"); + final String thumbnailUrl4 = AttachmentUtil.getThumbnailUrl(versionThatDoesNotSupportFileAttachments, accountUrl, 333L, attachment4, 444); + // ... a fallback to the attachment itself should be returned + assertEquals("https://example.com/index.php/apps/deck/cards/333/attachment/111", thumbnailUrl4); + } + +} diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/api/DeckAPI.java b/app/src/main/java/it/niedermann/nextcloud/deck/api/DeckAPI.java index a303a8a33..1f0148b91 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/api/DeckAPI.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/api/DeckAPI.java @@ -1,6 +1,8 @@ package it.niedermann.nextcloud.deck.api; +import com.nextcloud.android.sso.api.ParsedResponse; + import java.util.List; import io.reactivex.Observable; @@ -33,6 +35,7 @@ import retrofit2.http.Query; public interface DeckAPI { String MODIFIED_SINCE_HEADER = "If-Modified-Since"; + String IF_NONE_MATCH = "If-None-Match"; // ### BOARDS @POST("boards") @@ -51,7 +54,7 @@ public interface DeckAPI { Observable<FullBoard> restoreBoard(@Path("id") long id); @GET("boards") - Observable<List<FullBoard>> getBoards(@Query ("details") boolean verbose, @Header(MODIFIED_SINCE_HEADER) String lastSync ); + Observable<ParsedResponse<List<FullBoard>>> getBoards(@Query ("details") boolean verbose, @Header(MODIFIED_SINCE_HEADER) String lastSync, @Header(IF_NONE_MATCH) String eTag); // ### Stacks diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/api/IResponseCallback.java b/app/src/main/java/it/niedermann/nextcloud/deck/api/IResponseCallback.java index ddb16cd23..be3eaeb22 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/api/IResponseCallback.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/api/IResponseCallback.java @@ -35,6 +35,7 @@ public abstract class IResponseCallback<T> { public void onResponse(T response) { // Do Nothing } + }; } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/api/JsonToEntityParser.java b/app/src/main/java/it/niedermann/nextcloud/deck/api/JsonToEntityParser.java index 8601cab41..e759f27d4 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/api/JsonToEntityParser.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/api/JsonToEntityParser.java @@ -284,6 +284,7 @@ public class JsonToEntityParser { makeTraceableIfFails(() -> { board.setTitle(getNullAsEmptyString(e.get("title"))); board.setColor(getNullAsEmptyString(e.get("color"))); + board.setEtag(getNullAsNull(e.get("ETag"))); board.setArchived(e.get("archived").getAsBoolean()); board.setLastModified(getTimestampFromLong(e.get("lastModified"))); @@ -396,6 +397,7 @@ public class JsonToEntityParser { card.setDescription(getNullAsEmptyString(e.get("description"))); card.setStackId(e.get("stackId").getAsLong()); card.setType(getNullAsEmptyString(e.get("type"))); + card.setEtag(getNullAsNull(e.get("ETag"))); card.setLastModified(getTimestampFromLong(e.get("lastModified"))); card.setCreatedAt(getTimestampFromLong(e.get("createdAt"))); card.setDeletedAt(getTimestampFromLong(e.get("deletedAt"))); @@ -456,6 +458,7 @@ public class JsonToEntityParser { a.setId(e.get("id").getAsLong()); a.setCardId(e.get("cardId").getAsLong()); a.setType(e.get("type").getAsString()); + a.setEtag(getNullAsNull(e.get("ETag"))); a.setData(e.get("data").getAsString()); a.setLastModified(getTimestampFromLong(e.get("lastModified"))); a.setCreatedAt(getTimestampFromLong(e.get("createdAt"))); @@ -571,33 +574,6 @@ public class JsonToEntityParser { return Color.GRAY; } - protected static List<Activity> parseActivity(JsonObject e) { - DeckLog.verbose(e.toString()); - List<Activity> activityList = new ArrayList<>(); - - makeTraceableIfFails(() -> { - if (e.has("ocs")) { - JsonObject ocs = e.getAsJsonObject("ocs"); - if (ocs.has("data")) { - JsonArray data = ocs.getAsJsonArray("data"); - for (JsonElement activityJson : data) { - Activity activity = new Activity(); - JsonObject activityObject = activityJson.getAsJsonObject(); - - activity.setId(activityObject.get("activity_id").getAsLong()); - activity.setType(ActivityType.findByPath(getNullAsEmptyString(activityObject.get("icon"))).getId()); - activity.setSubject(getNullAsEmptyString(activityObject.get("subject"))); - activity.setCardId(activityObject.get("object_id").getAsLong()); - activity.setLastModified(getTimestampFromString(activityObject.get("datetime"))); - - activityList.add(activity); - } - } - } - }, e); - return activityList; - } - protected static FullStack parseStack(JsonObject e) { DeckLog.verbose(e.toString()); FullStack fullStack = new FullStack(); @@ -607,6 +583,7 @@ public class JsonToEntityParser { stack.setTitle(getNullAsEmptyString(e.get("title"))); stack.setBoardId(e.get("boardId").getAsLong()); stack.setId(e.get("id").getAsLong()); + stack.setEtag(getNullAsNull(e.get("ETag"))); stack.setLastModified(getTimestampFromLong(e.get("lastModified"))); stack.setDeletedAt(getTimestampFromLong(e.get("deletedAt"))); if (e.has("order") && !e.get("order").isJsonNull()) { @@ -627,6 +604,34 @@ public class JsonToEntityParser { return fullStack; } + protected static List<Activity> parseActivity(JsonObject e) { + DeckLog.verbose(e.toString()); + List<Activity> activityList = new ArrayList<>(); + + makeTraceableIfFails(() -> { + if (e.has("ocs")) { + JsonObject ocs = e.getAsJsonObject("ocs"); + if (ocs.has("data")) { + JsonArray data = ocs.getAsJsonArray("data"); + for (JsonElement activityJson : data) { + Activity activity = new Activity(); + JsonObject activityObject = activityJson.getAsJsonObject(); + + activity.setId(activityObject.get("activity_id").getAsLong()); + activity.setType(ActivityType.findByPath(getNullAsEmptyString(activityObject.get("icon"))).getId()); + activity.setSubject(getNullAsEmptyString(activityObject.get("subject"))); + activity.setCardId(activityObject.get("object_id").getAsLong()); + activity.setEtag(getNullAsNull(e.get("ETag"))); + activity.setLastModified(getTimestampFromString(activityObject.get("datetime"))); + + activityList.add(activity); + } + } + } + }, e); + return activityList; + } + protected static Label parseLabel(JsonObject e) { DeckLog.verbose(e.toString()); Label label = new Label(); @@ -635,13 +640,18 @@ public class JsonToEntityParser { //todo: last modified! // label.setLastModified(get); label.setTitle(getNullAsEmptyString(e.get("title"))); + label.setEtag(getNullAsNull(e.get("ETag"))); label.setColor(getColorAsInt(e, "color")); }, e); return label; } private static String getNullAsEmptyString(JsonElement jsonElement) { - return jsonElement.isJsonNull() ? "" : jsonElement.getAsString(); + return jsonElement == null || jsonElement.isJsonNull() ? "" : jsonElement.getAsString(); + } + + private static String getNullAsNull(JsonElement jsonElement) { + return jsonElement == null || jsonElement.isJsonNull() ? null : jsonElement.getAsString(); } private static Instant getTimestampFromString(JsonElement jsonElement) { diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/model/Account.java b/app/src/main/java/it/niedermann/nextcloud/deck/model/Account.java index 1c189d162..8abcbced7 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/model/Account.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/model/Account.java @@ -54,6 +54,7 @@ public class Account implements Serializable { private boolean maintenanceEnabled = false; private String etag; + private String boardsEtag; @Ignore public Account(Long id, @NonNull String name, @NonNull String userName, @NonNull String url) { @@ -190,6 +191,14 @@ public class Account implements Serializable { this.etag = etag; } + public String getBoardsEtag() { + return boardsEtag; + } + + public void setBoardsEtag(String boardsEtag) { + this.boardsEtag = boardsEtag; + } + /** * A cache buster parameter is added for duplicate account names on different hosts which shall be fetched from the same {@link SingleSignOnAccount} (e. g. {@link AccountSwitcherDialog}) * diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/model/Attachment.java b/app/src/main/java/it/niedermann/nextcloud/deck/model/Attachment.java index 5e3b988ef..7eabcbe70 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/model/Attachment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/model/Attachment.java @@ -2,6 +2,7 @@ package it.niedermann.nextcloud.deck.model; import androidx.room.Entity; import androidx.room.ForeignKey; +import androidx.room.Ignore; import androidx.room.Index; import java.io.Serializable; @@ -35,6 +36,9 @@ public class Attachment extends AbstractRemoteEntity implements Comparable<Attac private String extension; private String filename; private String localPath; + // TODO should probably be a Long... depends on https://github.com/nextcloud/deck/pull/2638 + @Ignore + private String fileId; public long getCardId() { return cardId; @@ -140,6 +144,22 @@ public class Attachment extends AbstractRemoteEntity implements Comparable<Attac this.localPath = localPath; } + /** + * TODO depends on https://github.com/nextcloud/deck/pull/2638 + */ + @Ignore + public String getFileId() { + return this.fileId; + } + + /** + * TODO depends on https://github.com/nextcloud/deck/pull/2638 + */ + @Ignore + public void setFileId(String fileId) { + this.fileId = fileId; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/model/Board.java b/app/src/main/java/it/niedermann/nextcloud/deck/model/Board.java index f88594e7f..27dcd1df8 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/model/Board.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/model/Board.java @@ -37,8 +37,8 @@ public class Board extends AbstractRemoteEntity implements Serializable { } @Ignore - public Board(String title, String color) { - this.title = title; + public Board(String title, @ColorInt int color) { + setTitle(title); setColor(color); } @@ -98,7 +98,7 @@ public class Board extends AbstractRemoteEntity implements Serializable { } } - public void setColor(Integer color) { + public void setColor(@ColorInt Integer color) { this.color = color; } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/model/interfaces/AbstractRemoteEntity.java b/app/src/main/java/it/niedermann/nextcloud/deck/model/interfaces/AbstractRemoteEntity.java index 54cd0fc31..2f7771383 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/model/interfaces/AbstractRemoteEntity.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/model/interfaces/AbstractRemoteEntity.java @@ -39,6 +39,8 @@ public abstract class AbstractRemoteEntity implements IRemoteEntity { protected Instant lastModified; protected Instant lastModifiedLocal; + protected String etag; + public AbstractRemoteEntity() { } @@ -137,6 +139,15 @@ public abstract class AbstractRemoteEntity implements IRemoteEntity { this.status = status.getId(); } + @Override + public String getEtag() { + return etag; + } + + @Override + public void setEtag(String etag) { + this.etag = etag; + } @Override public boolean equals(Object o) { diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/model/interfaces/IRemoteEntity.java b/app/src/main/java/it/niedermann/nextcloud/deck/model/interfaces/IRemoteEntity.java index f50bf0b90..f197c0d30 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/model/interfaces/IRemoteEntity.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/model/interfaces/IRemoteEntity.java @@ -68,6 +68,14 @@ public interface IRemoteEntity { getEntity().setStatusEnum(status); } + default String getEtag() { + return getEntity().getEtag(); + } + + default void setEtag(String etag) { + getEntity().setEtag(etag); + } + default <T> List<T> copyList(List<T> listToCopy) { if (listToCopy == null) { return null; 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 c04512ad2..cfd973831 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 @@ -10,12 +10,14 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import it.niedermann.nextcloud.deck.R; +import it.niedermann.nextcloud.deck.model.Attachment; import it.niedermann.nextcloud.deck.model.ocs.comment.DeckComment; public class Version implements Comparable<Version> { private static final Pattern NUMBER_EXTRACTION_PATTERN = Pattern.compile("[0-9]+"); 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); @Nullable private static Version VERSION_MINIMUM_SUPPORTED; @@ -155,6 +157,22 @@ public class Version implements Comparable<Version> { } /** + * Before {@link #VERSION_1_3_0} all {@link Attachment}s have been stored in a special folder at the server. + * Starting with {@link #VERSION_1_3_0} {@link Attachment}s can be stored as regular files, allowing for example to make use of server side thumbnail generation. + * <p> + * Since the migration takes a long time, it does not happen on upgrading the server app but step by step via a cronjob. + * Therefore this method is just an indicator, that it is possible that {@link Attachment}s are stored as files, but it is no guarantee that all {@link Attachment}s already have been migrated to files. + * + * @return whether or not the server supports file attachments + * @see <a href="https://github.com/nextcloud/deck/pull/2638">documentation in PR</a> + */ + public boolean supportsFileAttachments() { + return false; +// TODO depends on https://github.com/nextcloud/deck/pull/2638 +// return isGreaterOrEqualTo(VERSION_1_3_0); + } + + /** * Title max length has been increased from 100 to 255 characters beginning with server {@link Version} 1.0.0 * * @return the number of characters that the title fields of cards allow @@ -165,6 +183,7 @@ public class Version implements Comparable<Version> { ? 255 : 100; } + /** * URL to view a card in the web interface has been changed in {@link Version} 1.0.0 * diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java index c12a347ef..2f8d49ebb 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java @@ -1055,8 +1055,8 @@ public class SyncManager { // } @AnyThread - public LiveData<FullCard> createFullCard(long accountId, long localBoardId, long localStackId, @NonNull FullCard card) { - MutableLiveData<FullCard> liveData = new MutableLiveData<>(); + public WrappedLiveData<FullCard> createFullCard(long accountId, long localBoardId, long localStackId, @NonNull FullCard card) { + WrappedLiveData<FullCard> liveData = new WrappedLiveData<>(); doAsync(() -> { Account account = dataBaseAdapter.getAccountByIdDirectly(accountId); User owner = dataBaseAdapter.getUserByUidDirectly(accountId, account.getUserName()); @@ -1093,11 +1093,28 @@ public class SyncManager { } } - liveData.postValue(card); + if (serverAdapter.hasInternetConnection()) { new SyncHelper(serverAdapter, dataBaseAdapter, null) - .setResponseCallback(IResponseCallback.getDefaultResponseCallback(account)) + .setResponseCallback(new IResponseCallback<Boolean>(account) { + @Override + public void onResponse(Boolean response) { + liveData.postValue(card); + } + + @SuppressLint("MissingSuperCall") + @Override + public void onError(Throwable throwable) { + if (throwable.getClass() == DeckException.class && ((DeckException)throwable).getHint().equals(DeckException.Hint.DEPENDENCY_NOT_SYNCED_YET)) { + liveData.postValue(card); + } else { + liveData.postError(throwable); + } + } + }) .doUpSyncFor(new CardDataProvider(null, board, stack)); + } else { + liveData.postValue(card); } }); return liveData; diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/ServerAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/ServerAdapter.java index a0b9fd8aa..bff8ddfdb 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/ServerAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/ServerAdapter.java @@ -125,9 +125,9 @@ public class ServerAdapter { // return lastSyncHeader; } - public void getBoards(IResponseCallback<List<FullBoard>> responseCallback) { + public void getBoards(IResponseCallback<ParsedResponse<List<FullBoard>>> responseCallback) { RequestHelper.request(provider, () -> - provider.getDeckAPI().getBoards(true, getLastSyncDateFormatted(responseCallback.getAccount().getId())), + provider.getDeckAPI().getBoards(true, getLastSyncDateFormatted(responseCallback.getAccount().getId()), responseCallback.getAccount().getBoardsEtag()), responseCallback); } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java index 4da74f6a8..69b2abd1d 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java @@ -122,7 +122,7 @@ import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.dao.widgets.fil FilterWidgetSort.class, }, exportSchema = false, - version = 23 + version = 24 ) @TypeConverters({DateTypeConverter.class}) public abstract class DeckDatabase extends RoomDatabase { @@ -403,6 +403,25 @@ public abstract class DeckDatabase extends RoomDatabase { private static final Migration MIGRATION_22_23 = new Migration(22, 23) { @Override public void migrate(SupportSQLiteDatabase database) { + // https://github.com/stefan-niedermann/nextcloud-deck/issues/359 + database.execSQL("ALTER TABLE `Account` ADD `boardsEtag` TEXT"); + database.execSQL("ALTER TABLE `Board` ADD `etag` TEXT"); + database.execSQL("ALTER TABLE `Stack` ADD `etag` TEXT"); + database.execSQL("ALTER TABLE `Card` ADD `etag` TEXT"); + database.execSQL("ALTER TABLE `Label` ADD `etag` TEXT"); + database.execSQL("ALTER TABLE `AccessControl` ADD `etag` TEXT"); + database.execSQL("ALTER TABLE `Attachment` ADD `etag` TEXT"); + database.execSQL("ALTER TABLE `User` ADD `etag` TEXT"); + database.execSQL("ALTER TABLE `DeckComment` ADD `etag` TEXT"); + database.execSQL("ALTER TABLE `Activity` ADD `etag` TEXT"); + database.execSQL("ALTER TABLE `OcsProject` ADD `etag` TEXT"); + database.execSQL("ALTER TABLE `OcsProjectResource` ADD `etag` TEXT"); + } + }; + + private static final Migration MIGRATION_23_24 = new Migration(23, 24) { + @Override + public void migrate(SupportSQLiteDatabase database) { database.execSQL("CREATE TABLE `FilterWidget` (`id` INTEGER PRIMARY KEY AUTOINCREMENT)"); database.execSQL("CREATE TABLE `FilterWidgetAccount` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterWidgetId` INTEGER, `accountId` INTEGER, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterWidgetId`) REFERENCES `FilterWidget`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )"); database.execSQL("CREATE TABLE `FilterWidgetBoard` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterAccountId` INTEGER, `boardId` INTEGER, FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterAccountId`) REFERENCES `FilterWidgetAccount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )"); @@ -489,6 +508,7 @@ public abstract class DeckDatabase extends RoomDatabase { } }) .addMigrations(MIGRATION_22_23) + .addMigrations(MIGRATION_23_24) .fallbackToDestructiveMigration() .addCallback(ON_CREATE_CALLBACK) .build(); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/SyncHelper.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/SyncHelper.java index 032c3594a..17c0de2cf 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/SyncHelper.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/SyncHelper.java @@ -1,5 +1,11 @@ package it.niedermann.nextcloud.deck.persistence.sync.helpers; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException; + +import java.net.HttpURLConnection; import java.time.Instant; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -29,7 +35,7 @@ public class SyncHelper { } // Sync Server -> App - public <T extends IRemoteEntity> void doSyncFor(final AbstractSyncDataProvider<T> provider) { + public <T extends IRemoteEntity> void doSyncFor(@NonNull final AbstractSyncDataProvider<T> provider) { provider.registerChildInParent(provider); provider.getAllFromServer(serverAdapter, dataBaseAdapter, accountId, new IResponseCallback<List<T>>(account) { @Override @@ -50,12 +56,13 @@ public class SyncHelper { } else { //TODO: how to handle deletes? what about archived? if (existingEntity.getStatus() != DBStatus.UP_TO_DATE.getId()) { - DeckLog.log("Conflicting changes on entity: " + existingEntity); + DeckLog.warn("Conflicting changes on entity: " + existingEntity); // TODO: what to do? } else { -// if (existingEntity.getLastModified().getTime() == entityFromServer.getLastModified().getTime()) { -// continue; // TODO: is this is ok for sure? -> isn`t! NPE -// } + if (entityFromServer.getEtag() != null && entityFromServer.getEtag().equals(existingEntity.getEtag())) { + DeckLog.log("[" + provider.getClass().getSimpleName() + "] ETags do match! skipping " + existingEntity.getClass().getSimpleName() + " with localId: " + existingEntity.getLocalId()); + continue; + } provider.updateInDB(dataBaseAdapter, accountId, applyUpdatesFromRemote(provider, existingEntity, entityFromServer, accountId), false); } } @@ -73,20 +80,29 @@ public class SyncHelper { @Override public void onError(Throwable throwable) { + super.onError(throwable); + if (throwable.getClass() == NextcloudHttpRequestFailedException.class) { + NextcloudHttpRequestFailedException requestFailedException = (NextcloudHttpRequestFailedException) throwable; + if (HttpURLConnection.HTTP_NOT_MODIFIED == requestFailedException.getStatusCode()){ + DeckLog.log("[" + provider.getClass().getSimpleName() + "] ETags do match! skipping this one."); + // well, etags say we're fine here. no need to go deeper. + provider.childDone(provider, responseCallback, false); + return; + } + } provider.onError(throwable, responseCallback); - DeckLog.logError(throwable); responseCallback.onError(throwable); } }, lastSync); } // Sync App -> Server - public <T extends IRemoteEntity> void doUpSyncFor(AbstractSyncDataProvider<T> provider) { + public <T extends IRemoteEntity> void doUpSyncFor(@NonNull AbstractSyncDataProvider<T> provider) { doUpSyncFor(provider, null); } - public <T extends IRemoteEntity> void doUpSyncFor(AbstractSyncDataProvider<T> provider, CountDownLatch countDownLatch) { - List<T> allFromDB = provider.getAllChangedFromDB(dataBaseAdapter, accountId, lastSync); + public <T extends IRemoteEntity> void doUpSyncFor(@NonNull AbstractSyncDataProvider<T> provider, @Nullable CountDownLatch countDownLatch) { + final List<T> allFromDB = provider.getAllChangedFromDB(dataBaseAdapter, accountId, lastSync); if (allFromDB != null && !allFromDB.isEmpty()) { for (T entity : allFromDB) { if (entity.getId() != null) { @@ -110,7 +126,7 @@ public class SyncHelper { } } - private <T extends IRemoteEntity> IResponseCallback<Void> getDeleteCallback(AbstractSyncDataProvider<T> provider, T entity) { + private <T extends IRemoteEntity> IResponseCallback<Void> getDeleteCallback(@NonNull AbstractSyncDataProvider<T> provider, T entity) { return new IResponseCallback<Void>(account) { @Override public void onResponse(Void response) { @@ -126,7 +142,7 @@ public class SyncHelper { }; } - private <T extends IRemoteEntity> IResponseCallback<T> getUpdateCallback(AbstractSyncDataProvider<T> provider, T entity, CountDownLatch countDownLatch) { + private <T extends IRemoteEntity> IResponseCallback<T> getUpdateCallback(@NonNull AbstractSyncDataProvider<T> provider, @NonNull T entity, @Nullable CountDownLatch countDownLatch) { return new IResponseCallback<T>(account) { @Override public void onResponse(T response) { @@ -152,13 +168,13 @@ public class SyncHelper { }; } - public void fixRelations(IRelationshipProvider relationshipProvider) { + public void fixRelations(@NonNull IRelationshipProvider relationshipProvider) { // this is OK, since the delete only affects records with status UP_TO_DATE relationshipProvider.deleteAllExisting(dataBaseAdapter, accountId); relationshipProvider.insertAllNecessary(dataBaseAdapter, accountId); } - private <T extends IRemoteEntity> T applyUpdatesFromRemote(AbstractSyncDataProvider<T> provider, T localEntity, T remoteEntity, Long accountId) { + private <T extends IRemoteEntity> T applyUpdatesFromRemote(@NonNull AbstractSyncDataProvider<T> provider, @NonNull T localEntity, @NonNull T remoteEntity, @NonNull Long accountId) { if (!accountId.equals(localEntity.getAccountId())) { throw new IllegalArgumentException("IDs of Accounts are not matching! WTF are you doin?!"); } @@ -167,7 +183,7 @@ public class SyncHelper { return remoteEntity; } - public SyncHelper setResponseCallback(IResponseCallback<Boolean> callback) { + public SyncHelper setResponseCallback(@NonNull IResponseCallback<Boolean> callback) { this.responseCallback = callback; this.account = responseCallback.getAccount(); accountId = account.getId(); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/BoardDataProvider.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/BoardDataProvider.java index 5b458471f..f5e071adb 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/BoardDataProvider.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/BoardDataProvider.java @@ -1,5 +1,9 @@ package it.niedermann.nextcloud.deck.persistence.sync.helpers.providers; +import android.annotation.SuppressLint; + +import com.nextcloud.android.sso.api.ParsedResponse; + import java.time.Instant; import java.util.ArrayList; import java.util.Collections; @@ -26,8 +30,24 @@ public class BoardDataProvider extends AbstractSyncDataProvider<FullBoard> { } @Override - public void getAllFromServer(ServerAdapter serverAdapter, long accountId, IResponseCallback<List<FullBoard>> responder, Instant lastSync) { - serverAdapter.getBoards(responder); + public void getAllFromServer(ServerAdapter serverAdapter, DataBaseAdapter dataBaseAdapter, long accountId, IResponseCallback<List<FullBoard>> responder, Instant lastSync) { + serverAdapter.getBoards(new IResponseCallback<ParsedResponse<List<FullBoard>>>(responder.getAccount()) { + @Override + public void onResponse(ParsedResponse<List<FullBoard>> response) { + String etag = response.getHeaders().get("ETag"); + if (etag != null && !etag.equals(account.getBoardsEtag())) { + account.setBoardsEtag(etag); + dataBaseAdapter.updateAccount(account); + } + responder.onResponse(response.getResponse()); + } + + @SuppressLint("MissingSuperCall") + @Override + public void onError(Throwable throwable) { + responder.onError(throwable); + } + }); } @Override diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/CardDataProvider.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/CardDataProvider.java index 338b689f8..0ceac2cd8 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/CardDataProvider.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/CardDataProvider.java @@ -1,5 +1,7 @@ package it.niedermann.nextcloud.deck.persistence.sync.helpers.providers; +import android.annotation.SuppressLint; + import java.time.Instant; import java.util.ArrayList; import java.util.Collections; @@ -55,6 +57,7 @@ public class CardDataProvider extends AbstractSyncDataProvider<FullCard> { } } + @SuppressLint("MissingSuperCall") @Override public void onError(Throwable throwable) { responder.onError(throwable); @@ -151,12 +154,13 @@ public class CardDataProvider extends AbstractSyncDataProvider<FullCard> { @Override public void createOnServer(ServerAdapter serverAdapter, DataBaseAdapter dataBaseAdapter, long accountId, IResponseCallback<FullCard> responder, FullCard entity) { if (stack.getId() == null) { - throw new DeckException(DeckException.Hint.DEPENDENCY_NOT_SYNCED_YET, "Stack for this Card is not synced yet. Perform a full sync (pull to referesh) as soon as you are online again."); + responder.onError(new DeckException(DeckException.Hint.DEPENDENCY_NOT_SYNCED_YET, "Stack \"" + + stack.getStack().getTitle() + "\" for Card \"" + entity.getCard().getTitle() + + "\" is not synced yet. Perform a full sync (pull to refresh) as soon as you are online again.")); + return; } entity.getCard().setStackId(stack.getId()); -// if (board != null && stack != null && board.getId() != null && stack.getId() != null) { serverAdapter.createCard(board.getId(), stack.getId(), entity.getCard(), responder); -// } else DeckLog.error("Skipped card creation due to missing remote ID"); } @Override @@ -327,6 +331,7 @@ public class CardDataProvider extends AbstractSyncDataProvider<FullCard> { // do not delete, it's still there and was just moved! } + @SuppressLint("MissingSuperCall") @Override public void onError(Throwable throwable) { if (!(throwable instanceof OfflineException)) { diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java index 8a33fc0f1..5056985fa 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java @@ -470,12 +470,12 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener } @Override - public void onCreateBoard(String title, String color) { + public void onCreateBoard(String title, @ColorInt int color) { if (boardsLiveData == null || boardsLiveDataObserver == null) { throw new IllegalStateException("Cannot create board when noone observe boards yet. boardsLiveData or observer is null."); } boardsLiveData.removeObserver(boardsLiveDataObserver); - final Board boardToCreate = new Board(title, color.startsWith("#") ? color.substring(1) : color); + final Board boardToCreate = new Board(title, color); boardToCreate.setPermissionEdit(true); boardToCreate.setPermissionManage(true); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedboards/ArchivedBoardViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedboards/ArchivedBoardViewHolder.java index 67b2c00be..30f1e5d49 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedboards/ArchivedBoardViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedboards/ArchivedBoardViewHolder.java @@ -6,6 +6,7 @@ import android.view.MenuItem; import android.view.View; import androidx.appcompat.widget.PopupMenu; +import androidx.core.content.ContextCompat; import androidx.core.util.Consumer; import androidx.fragment.app.FragmentManager; import androidx.recyclerview.widget.RecyclerView; @@ -30,14 +31,13 @@ public class ArchivedBoardViewHolder extends RecyclerView.ViewHolder { void bind(boolean isSupportedVersion, Board board, FragmentManager fragmentManager, Consumer<Board> dearchiveBoardListener) { final Context context = itemView.getContext(); - binding.boardIcon.setImageDrawable(ViewUtil.getTintedImageView(binding.boardIcon.getContext(), R.drawable.circle_grey600_36dp, String.format("#%06X", (0xFFFFFF & board.getColor())))); + binding.boardIcon.setImageDrawable(ViewUtil.getTintedImageView(binding.boardIcon.getContext(), R.drawable.circle_grey600_36dp, board.getColor())); binding.boardMenu.setVisibility(View.GONE); binding.boardTitle.setText(board.getTitle()); if (isSupportedVersion) { if (board.isPermissionManage()) { binding.boardMenu.setVisibility(View.VISIBLE); - binding.boardMenu.setImageDrawable(ViewUtil.getTintedImageView(context, R.drawable.ic_menu, R.color.grey600)); - + binding.boardMenu.setImageDrawable(ViewUtil.getTintedImageView(context, R.drawable.ic_menu, ContextCompat.getColor(context, R.color.grey600))); binding.boardMenu.setOnClickListener((v) -> { PopupMenu popup = new PopupMenu(context, binding.boardMenu); popup.getMenuInflater().inflate(R.menu.archived_board_menu, popup.getMenu()); @@ -47,28 +47,27 @@ public class ArchivedBoardViewHolder extends RecyclerView.ViewHolder { } popup.setOnMenuItemClickListener((MenuItem item) -> { final String editBoard = context.getString(R.string.edit_board); - switch (item.getItemId()) { - case SHARE_BOARD_ID: - AccessControlDialogFragment.newInstance(board.getLocalId()).show(fragmentManager, AccessControlDialogFragment.class.getSimpleName()); - return true; - case R.id.edit_board: - EditBoardDialogFragment.newInstance(board.getLocalId()).show(fragmentManager, editBoard); - return true; - case R.id.dearchive_board: - dearchiveBoardListener.accept(board); - return true; - case R.id.delete_board: - DeleteBoardDialogFragment.newInstance(board).show(fragmentManager, DeleteBoardDialogFragment.class.getSimpleName()); - return true; - default: - return false; + int itemId = item.getItemId(); + if (itemId == SHARE_BOARD_ID) { + AccessControlDialogFragment.newInstance(board.getLocalId()).show(fragmentManager, AccessControlDialogFragment.class.getSimpleName()); + return true; + } else if (itemId == R.id.edit_board) { + EditBoardDialogFragment.newInstance(board.getLocalId()).show(fragmentManager, editBoard); + return true; + } else if (itemId == R.id.dearchive_board) { + dearchiveBoardListener.accept(board); + return true; + } else if (itemId == R.id.delete_board) { + DeleteBoardDialogFragment.newInstance(board).show(fragmentManager, DeleteBoardDialogFragment.class.getSimpleName()); + return true; } + return false; }); popup.show(); }); } else if (board.isPermissionShare()) { binding.boardMenu.setVisibility(View.VISIBLE); - binding.boardMenu.setImageDrawable(ViewUtil.getTintedImageView(context, R.drawable.ic_share_grey600_18dp, R.color.grey600)); + binding.boardMenu.setImageDrawable(ViewUtil.getTintedImageView(context, R.drawable.ic_share_grey600_18dp, ContextCompat.getColor(context, R.color.grey600))); binding.boardMenu.setOnClickListener((v) -> AccessControlDialogFragment.newInstance(board.getLocalId()).show(fragmentManager, AccessControlDialogFragment.class.getSimpleName())); } binding.boardMenu.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/attachments/AttachmentAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/attachments/AttachmentAdapter.java index b17b34137..c7d32bd37 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/attachments/AttachmentAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/attachments/AttachmentAdapter.java @@ -1,43 +1,31 @@ package it.niedermann.nextcloud.deck.ui.attachments; import android.content.Context; -import android.graphics.drawable.Drawable; -import android.os.Build; import android.view.LayoutInflater; import android.view.ViewGroup; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.FragmentActivity; import androidx.recyclerview.widget.RecyclerView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.DataSource; -import com.bumptech.glide.load.engine.GlideException; -import com.bumptech.glide.request.RequestListener; -import com.bumptech.glide.request.target.Target; - +import java.util.ArrayList; import java.util.List; -import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.databinding.ItemAttachmentBinding; import it.niedermann.nextcloud.deck.model.Account; import it.niedermann.nextcloud.deck.model.Attachment; -import it.niedermann.nextcloud.deck.util.AttachmentUtil; -import it.niedermann.nextcloud.deck.util.MimeTypeUtil; public class AttachmentAdapter extends RecyclerView.Adapter<AttachmentViewHolder> { private final Account account; private final long cardRemoteId; @NonNull - private List<Attachment> attachments; - private Context context; + private final List<Attachment> attachments = new ArrayList<>(); @SuppressWarnings("WeakerAccess") public AttachmentAdapter(@NonNull Account account, long cardRemoteId, @NonNull List<Attachment> attachments) { super(); - this.attachments = attachments; + this.attachments.clear(); + this.attachments.addAll(attachments); this.account = account; this.cardRemoteId = cardRemoteId; } @@ -45,43 +33,13 @@ public class AttachmentAdapter extends RecyclerView.Adapter<AttachmentViewHolder @NonNull @Override public AttachmentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - this.context = parent.getContext(); - return new AttachmentViewHolder(ItemAttachmentBinding.inflate(LayoutInflater.from(context), parent, false)); + final Context context = parent.getContext(); + return new AttachmentViewHolder(context, ItemAttachmentBinding.inflate(LayoutInflater.from(context), parent, false)); } @Override public void onBindViewHolder(@NonNull AttachmentViewHolder holder, int position) { - final Attachment attachment = attachments.get(position); - final String uri = AttachmentUtil.getRemoteOrLocalUrl(account.getUrl(), cardRemoteId, attachment); - if (MimeTypeUtil.isImage(attachment.getMimetype())) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - holder.binding.preview.setTransitionName(context.getString(R.string.transition_attachment_preview, String.valueOf(attachment.getLocalId()))); - } - holder.binding.preview.setImageResource(R.drawable.ic_image_grey600_24dp); - Glide.with(context) - .load(uri) - .listener(new RequestListener<Drawable>() { - @Override - public boolean onLoadFailed(@Nullable GlideException e, Object model, - Target<Drawable> target, boolean isFirstResource) { - if (context instanceof FragmentActivity) { - ((FragmentActivity) context).supportStartPostponedEnterTransition(); - } - return false; - } - - @Override - public boolean onResourceReady(Drawable resource, Object model, - Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { - if (context instanceof FragmentActivity) { - ((FragmentActivity) context).supportStartPostponedEnterTransition(); - } - return false; - } - }) - .error(R.drawable.ic_image_grey600_24dp) - .into(holder.binding.preview); - } + holder.bind(account, attachments.get(position), cardRemoteId); } @Override diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/attachments/AttachmentViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/attachments/AttachmentViewHolder.java index 584a57d1d..6f4fe3c74 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/attachments/AttachmentViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/attachments/AttachmentViewHolder.java @@ -1,15 +1,72 @@ package it.niedermann.nextcloud.deck.ui.attachments; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Build; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; import androidx.recyclerview.widget.RecyclerView; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; + +import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.databinding.ItemAttachmentBinding; +import it.niedermann.nextcloud.deck.model.Account; +import it.niedermann.nextcloud.deck.model.Attachment; +import it.niedermann.nextcloud.deck.util.AttachmentUtil; +import it.niedermann.nextcloud.deck.util.MimeTypeUtil; public class AttachmentViewHolder extends RecyclerView.ViewHolder { - public ItemAttachmentBinding binding; + @NonNull + private final Context parentContext; + @NonNull + private final ItemAttachmentBinding binding; @SuppressWarnings("WeakerAccess") - public AttachmentViewHolder(ItemAttachmentBinding binding) { + public AttachmentViewHolder(@NonNull Context parentContext, @NonNull ItemAttachmentBinding binding) { super(binding.getRoot()); + this.parentContext = parentContext; this.binding = binding; } + + public void bind(@NonNull Account account, @NonNull Attachment attachment, long cardRemoteId) { + if (MimeTypeUtil.isImage(attachment.getMimetype())) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + binding.preview.setTransitionName(parentContext.getString(R.string.transition_attachment_preview, String.valueOf(attachment.getLocalId()))); + } + binding.preview.setImageResource(R.drawable.ic_image_grey600_24dp); + binding.preview.post(() -> { + final String uri = AttachmentUtil.getThumbnailUrl(account.getServerDeckVersionAsObject(), account.getUrl(), cardRemoteId, attachment, binding.preview.getWidth()); + Glide.with(parentContext) + .load(uri) + .listener(new RequestListener<Drawable>() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, + Target<Drawable> target, boolean isFirstResource) { + if (parentContext instanceof FragmentActivity) { + ((FragmentActivity) parentContext).supportStartPostponedEnterTransition(); + } + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, + Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { + if (parentContext instanceof FragmentActivity) { + ((FragmentActivity) parentContext).supportStartPostponedEnterTransition(); + } + return false; + } + }) + .error(R.drawable.ic_image_grey600_24dp) + .into(binding.preview); + }); + } + } }
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/BoardAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/BoardAdapter.java index 5975e0306..c9501ffa9 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/BoardAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/BoardAdapter.java @@ -37,7 +37,7 @@ public class BoardAdapter extends ArrayAdapter<Board> { TextView boardName = convertView.findViewById(R.id.boardName); if (board != null) { boardName.setText(board.getTitle()); - boardName.setCompoundDrawables(ViewUtil.getTintedImageView(context, R.drawable.circle_grey600_36dp, String.format("#%06X", (0xFFFFFF & board.getColor()))), null, null, null); + boardName.setCompoundDrawables(ViewUtil.getTintedImageView(context, R.drawable.circle_grey600_36dp, board.getColor()), null, null, null); } else { DeckLog.logError(new IllegalArgumentException("board at position " + position + "is null")); } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java index e197727d5..1ee23abfa 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java @@ -56,7 +56,7 @@ public class EditBoardDialogFragment extends BrandedDialogFragment { dialogBuilder.setPositiveButton(R.string.simple_save, (dialog, which) -> { this.fullBoard.board.setColor(binding.colorChooser.getSelectedColor()); this.fullBoard.board.setTitle(binding.input.getText().toString()); - editBoardListener.onUpdateBoard(fullBoard); + this.editBoardListener.onUpdateBoard(fullBoard); }); final MainViewModel viewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class); new SyncManager(requireActivity()).getFullBoardById(viewModel.getCurrentAccount().getId(), args.getLong(KEY_BOARD_ID)).observe(EditBoardDialogFragment.this, (FullBoard fb) -> { @@ -65,13 +65,13 @@ public class EditBoardDialogFragment extends BrandedDialogFragment { String title = this.fullBoard.getBoard().getTitle(); binding.input.setText(title); binding.input.setSelection(title.length()); - binding.colorChooser.selectColor(String.format("#%06X", (0xFFFFFF & fullBoard.getBoard().getColor()))); + binding.colorChooser.selectColor(fullBoard.getBoard().getColor()); } }); } else { dialogBuilder.setTitle(R.string.add_board); dialogBuilder.setPositiveButton(R.string.simple_add, (dialog, which) -> editBoardListener.onCreateBoard(binding.input.getText().toString(), binding.colorChooser.getSelectedColor())); - binding.colorChooser.selectColor(String.format("#%06X", 0xFFFFFF & ContextCompat.getColor(requireContext(), R.color.board_default_color))); + binding.colorChooser.selectColor(ContextCompat.getColor(requireContext(), R.color.board_default_color)); } return dialogBuilder diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardListener.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardListener.java index ee9ba9b9d..9d8fcdbde 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardListener.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardListener.java @@ -1,11 +1,13 @@ package it.niedermann.nextcloud.deck.ui.board; +import androidx.annotation.ColorInt; + import it.niedermann.nextcloud.deck.model.full.FullBoard; public interface EditBoardListener { void onUpdateBoard(FullBoard fullBoard); - default void onCreateBoard(String title, String color) { + default void onCreateBoard(String title, @ColorInt int color) { // Creating board is not necessary } }
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/EditLabelDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/EditLabelDialogFragment.java index a0fb4cadd..2dacfe6ac 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/EditLabelDialogFragment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/EditLabelDialogFragment.java @@ -65,7 +65,7 @@ public class EditLabelDialogFragment extends BrandedDialogFragment { String title = this.label.getTitle(); binding.input.setText(title); binding.input.setSelection(title.length()); - binding.colorChooser.selectColor(String.format("#%06X", (0xFFFFFF & this.label.getColor()))); + binding.colorChooser.selectColor(this.label.getColor()); return dialogBuilder .setView(binding.getRoot()) diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/activities/CardActivityViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/activities/CardActivityViewHolder.java index f8d237ad4..6362f90dd 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/activities/CardActivityViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/activities/CardActivityViewHolder.java @@ -3,6 +3,7 @@ package it.niedermann.nextcloud.deck.ui.card.activities; import android.content.Context; import android.view.MenuInflater; import android.view.View; +import android.widget.ImageView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; @@ -13,6 +14,7 @@ import it.niedermann.nextcloud.deck.databinding.ItemActivityBinding; import it.niedermann.nextcloud.deck.model.enums.ActivityType; import it.niedermann.nextcloud.deck.model.ocs.Activity; import it.niedermann.nextcloud.deck.util.DateUtil; +import it.niedermann.nextcloud.deck.util.ViewUtil; public class CardActivityViewHolder extends RecyclerView.ViewHolder { public ItemActivityBinding binding; @@ -32,31 +34,54 @@ public class CardActivityViewHolder extends RecyclerView.ViewHolder { inflater.inflate(R.menu.activity_menu, menu); menu.findItem(android.R.id.copy).setOnMenuItemClickListener(item -> ClipboardUtil.INSTANCE.copyToClipboard(context, activity.getSubject())); }); - switch (ActivityType.findById(activity.getType())) { + final ActivityType type = ActivityType.findById(activity.getType()); + setImageResource(binding.type, type); + setImageColor(context, binding.type, type); + } + + private static void setImageResource(@NonNull ImageView imageView, @NonNull ActivityType type) { + switch (type) { case CHANGE: - binding.type.setImageResource(R.drawable.type_change_36dp); + imageView.setImageResource(R.drawable.type_change_36dp); break; case ADD: - binding.type.setImageResource(R.drawable.type_add_color_36dp); + imageView.setImageResource(R.drawable.type_add_color_36dp); break; case DELETE: - binding.type.setImageResource(R.drawable.type_delete_color_36dp); + imageView.setImageResource(R.drawable.type_delete_color_36dp); break; case ARCHIVE: - binding.type.setImageResource(R.drawable.type_archive_grey600_36dp); + imageView.setImageResource(R.drawable.type_archive_grey600_36dp); break; case TAGGED_WITH_LABEL: - binding.type.setImageResource(R.drawable.type_label_grey600_36dp); + imageView.setImageResource(R.drawable.type_label_grey600_36dp); break; case COMMENT: - binding.type.setImageResource(R.drawable.type_comment_grey600_36dp); + imageView.setImageResource(R.drawable.type_comment_grey600_36dp); break; case FILES: - binding.type.setImageResource(R.drawable.type_file_36dp); + imageView.setImageResource(R.drawable.type_file_36dp); + break; case HISTORY: - binding.type.setImageResource(R.drawable.type_history_36dp); + imageView.setImageResource(R.drawable.type_history_36dp); + break; case DECK: default: + imageView.setImageResource(R.drawable.ic_app_logo); + break; + } + } + + private static void setImageColor(@NonNull Context context, @NonNull ImageView imageView, @NonNull ActivityType type) { + switch (type) { + case ADD: + ViewUtil.setImageColor(context, imageView, R.color.activity_create); + break; + case DELETE: + ViewUtil.setImageColor(context, imageView, R.color.activity_delete); + break; + default: + ViewUtil.setImageColor(context, imageView, R.color.grey600); break; } } 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 bb42f27ef..81a166cb6 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 @@ -233,9 +233,9 @@ public class CardAttachmentsFragment extends BrandedFragment implements Attachme binding.emptyContentView.hideDescription(); } @Nullable Context context = requireContext(); - if (isBrandingEnabled(context)) { - applyBrand(readBrandMainColor(context)); - } + applyBrand(isBrandingEnabled(context) + ? readBrandMainColor(context) + : ContextCompat.getColor(context, R.color.defaultBrand)); return binding.getRoot(); } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/ImageAttachmentViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/ImageAttachmentViewHolder.java index e3139295f..3c95da1b7 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/ImageAttachmentViewHolder.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/ImageAttachmentViewHolder.java @@ -18,7 +18,7 @@ import it.niedermann.nextcloud.deck.model.Attachment; import it.niedermann.nextcloud.deck.util.AttachmentUtil; public class ImageAttachmentViewHolder extends AttachmentViewHolder { - private ItemAttachmentImageBinding binding; + private final ItemAttachmentImageBinding binding; @SuppressWarnings("WeakerAccess") public ImageAttachmentViewHolder(ItemAttachmentImageBinding binding) { @@ -37,16 +37,17 @@ public class ImageAttachmentViewHolder extends AttachmentViewHolder { } public void bind(@NonNull Account account, @NonNull MenuInflater menuInflater, @NonNull FragmentManager fragmentManager, Long cardRemoteId, Attachment attachment, @Nullable View.OnClickListener onClickListener, @ColorInt int mainColor) { - @Nullable final String uri = AttachmentUtil.getRemoteOrLocalUrl(account.getUrl(), cardRemoteId, attachment); + super.bind(menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, mainColor, AttachmentUtil.getRemoteOrLocalUrl(account.getUrl(), cardRemoteId, attachment)); - super.bind(menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, mainColor, uri); + getPreview().post(() -> { + @Nullable final String uri = AttachmentUtil.getThumbnailUrl(account.getServerDeckVersionAsObject(), account.getUrl(), cardRemoteId, attachment, getPreview().getWidth()); + Glide.with(getPreview().getContext()) + .load(uri) + .placeholder(R.drawable.ic_image_grey600_24dp) + .error(R.drawable.ic_image_grey600_24dp) + .into(getPreview()); + }); - getPreview().setImageResource(R.drawable.ic_image_grey600_24dp); - Glide.with(getPreview().getContext()) - .load(uri) - .placeholder(R.drawable.ic_image_grey600_24dp) - .error(R.drawable.ic_image_grey600_24dp) - .into(getPreview()); itemView.setOnClickListener(onClickListener); } }
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/BoardAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/BoardAdapter.java index 558a22db4..c27fa04ee 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/BoardAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/BoardAdapter.java @@ -37,7 +37,7 @@ public class BoardAdapter extends AbstractAdapter<Board> { final Board item = getItem(position); if (item != null) { binding.boardTitle.setText(item.getTitle()); - binding.avatar.setImageDrawable(ViewUtil.getTintedImageView(binding.avatar.getContext(), R.drawable.circle_grey600_36dp, String.format("#%06X", (0xFFFFFF & item.getColor())))); + binding.avatar.setImageDrawable(ViewUtil.getTintedImageView(binding.avatar.getContext(), R.drawable.circle_grey600_36dp, item.getColor())); } else { DeckLog.logError(new IllegalArgumentException("No item for position " + position)); } 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 c82f47c9c..0dd431ff9 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 @@ -2,6 +2,7 @@ package it.niedermann.nextcloud.deck.ui.view; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.Color; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -9,11 +10,15 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; +import androidx.annotation.ColorInt; import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; import com.google.android.flexbox.FlexboxLayout; 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; @@ -24,10 +29,12 @@ public class ColorChooser extends LinearLayout { private final WidgetColorChooserBinding binding; private final Context context; - private final String[] colors; + private final int[] colors; - private String selectedColor; - private String previouslySelectedColor; + @ColorInt + private int selectedColor; + @ColorInt + private int previouslySelectedColor; @Nullable private ImageView previouslySelectedImageView; @@ -42,14 +49,15 @@ public class ColorChooser extends LinearLayout { params.setMargins(0, DimensionUtil.INSTANCE.dpToPx(context, R.dimen.spacer_1x), 0, 0); params.setFlexBasisPercent(.15f); - TypedArray a = context.obtainStyledAttributes(attrs, - R.styleable.ColorChooser, 0, 0); - colors = getResources().getStringArray(a.getResourceId(R.styleable.ColorChooser_colors, 0)); + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ColorChooser, 0, 0); + colors = Arrays.stream(getResources().getStringArray(a.getResourceId(R.styleable.ColorChooser_colors, 0))) + .mapToInt(Color::parseColor) + .toArray(); a.recycle(); binding = WidgetColorChooserBinding.inflate(LayoutInflater.from(context), this, true); - for (final String color : colors) { - ImageView image = new ImageView(getContext()); + for (final int color : colors) { + final ImageView image = new ImageView(getContext()); image.setLayoutParams(params); image.setOnClickListener((imageView) -> { if (previouslySelectedImageView != null) { // null when first selection @@ -59,7 +67,7 @@ public class ColorChooser extends LinearLayout { selectedColor = color; this.previouslySelectedColor = color; this.previouslySelectedImageView = image; - binding.customColorChooser.setImageDrawable(ViewUtil.getTintedImageView(this.context, R.drawable.circle_alpha_colorize_36dp, R.color.board_default_custom_color)); + binding.customColorChooser.setImageDrawable(ViewUtil.getTintedImageView(this.context, R.drawable.circle_alpha_colorize_36dp, ContextCompat.getColor(context, R.color.board_default_custom_color))); binding.customColorPicker.setVisibility(View.GONE); binding.brightnessSlide.setVisibility(View.GONE); }); @@ -82,19 +90,20 @@ public class ColorChooser extends LinearLayout { previouslySelectedImageView.setImageDrawable(ViewUtil.getTintedImageView(this.context, R.drawable.circle_grey600_36dp, previouslySelectedColor)); previouslySelectedImageView = null; } - String customColor = "#" + envelope.getHexCode().substring(2); + @ColorInt + final int customColor = envelope.getColor(); selectedColor = customColor; previouslySelectedColor = customColor; binding.customColorChooser.setImageDrawable(ViewUtil.getTintedImageView(context, R.drawable.circle_alpha_colorize_36dp, selectedColor)); }); } - public void selectColor(String newColor) { + public void selectColor(@ColorInt int newColor) { boolean newColorIsCustomColor = true; selectedColor = newColor; for (int i = 0; i < colors.length; i++) { - if (colors[i].equals(newColor)) { - binding.customColorChooser.setImageDrawable(ViewUtil.getTintedImageView(this.context, R.drawable.circle_alpha_colorize_36dp, R.color.board_default_custom_color)); + if (colors[i] == newColor) { + binding.customColorChooser.setImageDrawable(ViewUtil.getTintedImageView(this.context, R.drawable.circle_alpha_colorize_36dp, ContextCompat.getColor(context, R.color.board_default_custom_color))); binding.colorPicker.getChildAt(i).performClick(); newColorIsCustomColor = false; break; @@ -105,7 +114,8 @@ public class ColorChooser extends LinearLayout { } } - public String getSelectedColor() { + @ColorInt + public int getSelectedColor() { return this.selectedColor; } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/stack/StackWidgetConfigurationActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/stack/StackWidgetConfigurationActivity.java index 6b86b50ba..771feabc2 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/stack/StackWidgetConfigurationActivity.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/stack/StackWidgetConfigurationActivity.java @@ -7,6 +7,7 @@ import android.os.Bundle; import androidx.appcompat.app.ActionBar; import it.niedermann.nextcloud.deck.DeckLog; +import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.model.Account; import it.niedermann.nextcloud.deck.ui.PickStackActivity; @@ -18,7 +19,7 @@ public class StackWidgetConfigurationActivity extends PickStackActivity { super.onCreate(savedInstanceState); final ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { - actionBar.setTitle("Add stack widget"); + actionBar.setTitle(R.string.add_stack_widget); } setResult(RESULT_CANCELED); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/AttachmentUtil.java b/app/src/main/java/it/niedermann/nextcloud/deck/util/AttachmentUtil.java index 2baec8e92..ef3e14b37 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/util/AttachmentUtil.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/util/AttachmentUtil.java @@ -10,6 +10,7 @@ import android.widget.Toast; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.Px; import java.io.File; import java.io.FileNotFoundException; @@ -20,6 +21,7 @@ import java.io.InputStream; import it.niedermann.nextcloud.deck.DeckLog; import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.model.Attachment; +import it.niedermann.nextcloud.deck.model.ocs.Version; /** * Created by stefan on 07.03.20. @@ -31,7 +33,19 @@ public class AttachmentUtil { } /** - * @return {@link AttachmentUtil#getRemoteUrl} or {@link Attachment#getLocalPath()} as fallback in case this {@param attachment} has not yet been synced. + * @return a link to the thumbnail of the given {@link Attachment}. + * If a thumbnail is not available (see {@link Version#supportsFileAttachments()}), a link to + * the {@link Attachment} itself will be returned instead. + */ + public static String getThumbnailUrl(@NonNull Version version, @NonNull String accountUrl, @NonNull Long cardRemoteId, @NonNull Attachment attachment, @Px int previewSize) { + return version.supportsFileAttachments() && !TextUtils.isEmpty(String.valueOf(attachment.getFileId())) + ? accountUrl + "/index.php/core/preview?fileId=" + attachment.getFileId() + "&x=" + previewSize + "&y=" + previewSize + : getRemoteOrLocalUrl(accountUrl, cardRemoteId, attachment); + } + + /** + * @return {@link AttachmentUtil#getRemoteUrl} or {@link Attachment#getLocalPath()} as fallback + * in case this {@param attachment} has not yet been synced. */ @Nullable public static String getRemoteOrLocalUrl(@NonNull String accountUrl, @Nullable Long cardRemoteId, @NonNull Attachment attachment) { diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/DrawerMenuUtil.java b/app/src/main/java/it/niedermann/nextcloud/deck/util/DrawerMenuUtil.java index 1f6490bf2..1a88bec97 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/util/DrawerMenuUtil.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/util/DrawerMenuUtil.java @@ -7,6 +7,7 @@ import android.view.SubMenu; import androidx.annotation.NonNull; import androidx.appcompat.widget.AppCompatImageButton; import androidx.appcompat.widget.PopupMenu; +import androidx.core.content.ContextCompat; import androidx.fragment.app.FragmentActivity; import java.util.List; @@ -38,12 +39,12 @@ public class DrawerMenuUtil { SubMenu boardsMenu = menu.addSubMenu(R.string.simple_boards); int index = 0; for (Board board : boards) { - MenuItem m = boardsMenu.add(Menu.NONE, index++, Menu.NONE, board.getTitle()).setIcon(ViewUtil.getTintedImageView(context, R.drawable.circle_grey600_36dp, String.format("#%06X", (0xFFFFFF & board.getColor())))); + MenuItem m = boardsMenu.add(Menu.NONE, index++, Menu.NONE, board.getTitle()).setIcon(ViewUtil.getTintedImageView(context, R.drawable.circle_grey600_36dp, board.getColor())); if (currentServerVersionIsSupported) { if (board.isPermissionManage()) { AppCompatImageButton contextMenu = new AppCompatImageButton(context); contextMenu.setBackgroundDrawable(null); - contextMenu.setImageDrawable(ViewUtil.getTintedImageView(context, R.drawable.ic_menu, R.color.grey600)); + contextMenu.setImageDrawable(ViewUtil.getTintedImageView(context, R.drawable.ic_menu, ContextCompat.getColor(context, R.color.grey600))); contextMenu.setOnClickListener((v) -> { PopupMenu popup = new PopupMenu(context, contextMenu); popup.getMenuInflater().inflate(R.menu.navigation_context_menu, popup.getMenu()); @@ -53,28 +54,27 @@ public class DrawerMenuUtil { } popup.setOnMenuItemClickListener((MenuItem item) -> { final String editBoard = context.getString(R.string.edit_board); - switch (item.getItemId()) { - case SHARE_BOARD_ID: - AccessControlDialogFragment.newInstance(board.getLocalId()).show(context.getSupportFragmentManager(), AccessControlDialogFragment.class.getSimpleName()); - return true; - case R.id.edit_board: - EditBoardDialogFragment.newInstance(board.getLocalId()).show(context.getSupportFragmentManager(), editBoard); - return true; - case R.id.manage_labels: - ManageLabelsDialogFragment.newInstance(board.getLocalId()).show(context.getSupportFragmentManager(), editBoard); - return true; - case R.id.clone_board: - context.onClone(board); - return true; - case R.id.archive_board: - context.onArchive(board); - return true; - case R.id.delete_board: - DeleteBoardDialogFragment.newInstance(board).show(context.getSupportFragmentManager(), DeleteBoardDialogFragment.class.getCanonicalName()); - return true; - default: - return false; + int itemId = item.getItemId(); + if (itemId == SHARE_BOARD_ID) { + AccessControlDialogFragment.newInstance(board.getLocalId()).show(context.getSupportFragmentManager(), AccessControlDialogFragment.class.getSimpleName()); + return true; + } else if (itemId == R.id.edit_board) { + EditBoardDialogFragment.newInstance(board.getLocalId()).show(context.getSupportFragmentManager(), editBoard); + return true; + } else if (itemId == R.id.manage_labels) { + ManageLabelsDialogFragment.newInstance(board.getLocalId()).show(context.getSupportFragmentManager(), editBoard); + return true; + } else if (itemId == R.id.clone_board) { + context.onClone(board); + return true; + } else if (itemId == R.id.archive_board) { + context.onArchive(board); + return true; + } else if (itemId == R.id.delete_board) { + DeleteBoardDialogFragment.newInstance(board).show(context.getSupportFragmentManager(), DeleteBoardDialogFragment.class.getCanonicalName()); + return true; } + return false; }); popup.show(); }); @@ -82,7 +82,7 @@ public class DrawerMenuUtil { } else if (board.isPermissionShare()) { AppCompatImageButton contextMenu = new AppCompatImageButton(context); contextMenu.setBackgroundDrawable(null); - contextMenu.setImageDrawable(ViewUtil.getTintedImageView(context, R.drawable.ic_share_grey600_18dp, R.color.grey600)); + contextMenu.setImageDrawable(ViewUtil.getTintedImageView(context, R.drawable.ic_share_grey600_18dp, ContextCompat.getColor(context, R.color.grey600))); contextMenu.setOnClickListener((v) -> AccessControlDialogFragment.newInstance(board.getLocalId()).show(context.getSupportFragmentManager(), AccessControlDialogFragment.class.getSimpleName())); m.setActionView(contextMenu); } @@ -90,7 +90,7 @@ public class DrawerMenuUtil { } if (hasArchivedBoards) { - boardsMenu.add(Menu.NONE, MENU_ID_ARCHIVED_BOARDS, Menu.NONE, R.string.archived_boards).setIcon(ViewUtil.getTintedImageView(context, R.drawable.ic_archive_white_24dp, R.color.grey600)); + boardsMenu.add(Menu.NONE, MENU_ID_ARCHIVED_BOARDS, Menu.NONE, R.string.archived_boards).setIcon(ViewUtil.getTintedImageView(context, R.drawable.ic_archive_white_24dp, ContextCompat.getColor(context, R.color.grey600))); } if (currentServerVersionIsSupported) { diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/ProjectUtil.java b/app/src/main/java/it/niedermann/nextcloud/deck/util/ProjectUtil.java index 015241eef..58c465290 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/util/ProjectUtil.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/util/ProjectUtil.java @@ -33,7 +33,7 @@ public class ProjectUtil { /** * extracts the values of board- and card-ID from url. - * Depending on what kind of url it gets, it will return a long[] of lenght 1 or 2: + * Depending on what kind of url it gets, it will return a long[] of length 1 or 2: * If the url contains both values, you'll get 2, if it contains only the board, you'll get 1. * <p> * The order is fixed here: [boardId, cardId] @@ -46,11 +46,14 @@ public class ProjectUtil { throw new IllegalArgumentException("provided url is null"); } url = url.trim(); + if (url.length() == 0) { + throw new IllegalArgumentException("trimmed url is empty"); + } // extract important part - String[] splitByPrefix = url.split(".*index\\.php/apps/deck/#/board/"); + String[] splitByPrefix = url.split(".*(index\\.php/)?apps/deck(/#)?/board/"); // split into board- and card part if (splitByPrefix.length < 2) { - throw new IllegalArgumentException("this doesn't seem to be an URL containing the board ID"); + throw new IllegalArgumentException("This URL doesn't seem to be an URL containing the boardId: \"" + url + "\""); } String[] splitBySeparator = splitByPrefix[1].split("/card/"); @@ -63,13 +66,13 @@ public class ProjectUtil { } if (splitBySeparator.length < 1) { - throw new IllegalArgumentException("this doesn't seem to be a valid URL containing the board ID"); + throw new IllegalArgumentException("This URL doesn't seem to be an URL containing the boardId: \"" + url + "\""); } // return result long boardId = Long.parseLong(splitBySeparator[0]); if (boardId < 1) { - throw new IllegalArgumentException("invalid boardId: "+boardId); + throw new IllegalArgumentException("Invalid boardId \"" + boardId + "\" for url \"" + url + "\"."); } if (splitBySeparator.length == 1) { return new long[]{boardId}; @@ -81,7 +84,7 @@ public class ProjectUtil { return new long[]{boardId}; } } else { - throw new IllegalArgumentException("could not parse URL for board- and/or card-ID"); + throw new IllegalArgumentException("could not parse URL for boardId and/or cardId: \"" + url + "\""); } } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/ViewUtil.java b/app/src/main/java/it/niedermann/nextcloud/deck/util/ViewUtil.java index b676fcedb..fbc7fc3fc 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/util/ViewUtil.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/util/ViewUtil.java @@ -3,7 +3,6 @@ package it.niedermann.nextcloud.deck.util; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Bitmap; -import android.graphics.Color; import android.graphics.drawable.Drawable; import android.net.Uri; import android.text.Spannable; @@ -12,6 +11,8 @@ import android.text.style.ImageSpan; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ColorInt; +import androidx.annotation.ColorRes; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -33,6 +34,8 @@ import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.model.Account; import it.niedermann.nextcloud.deck.model.ocs.comment.Mention; +import static android.os.Build.VERSION.SDK_INT; +import static android.os.Build.VERSION_CODES.LOLLIPOP; import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme; import static java.time.temporal.ChronoUnit.DAYS; @@ -77,18 +80,14 @@ public final class ViewUtil { TextViewCompat.setCompoundDrawableTintList(cardDueDate, ColorStateList.valueOf(ContextCompat.getColor(context, textColor))); } - public static Drawable getTintedImageView(@NonNull Context context, @DrawableRes int imageId, @NonNull String color) { + public static Drawable getTintedImageView(@NonNull Context context, @DrawableRes int imageId, @ColorInt int color) { final Drawable drawable = ContextCompat.getDrawable(context, imageId); assert drawable != null; final Drawable wrapped = DrawableCompat.wrap(drawable).mutate(); - DrawableCompat.setTint(wrapped, Color.parseColor(color)); + DrawableCompat.setTint(wrapped, color); return drawable; } - public static Drawable getTintedImageView(@NonNull Context context, @DrawableRes int imageId, int colorId) { - return getTintedImageView(context, imageId, context.getResources().getString(colorId)); - } - /** * Replaces all mentions in the textView with an avatar and the display name * @@ -140,4 +139,12 @@ public final class ViewUtil { } textView.setText(messageBuilder); } + + public static void setImageColor(@NonNull Context context, @NonNull ImageView imageView, @ColorRes int colorRes) { + if (SDK_INT >= LOLLIPOP) { + imageView.setImageTintList(ColorStateList.valueOf(ContextCompat.getColor(context, colorRes))); + } else { + imageView.setColorFilter(ContextCompat.getColor(context, colorRes)); + } + } } diff --git a/app/src/main/res/drawable/type_add_color_36dp.xml b/app/src/main/res/drawable/type_add_color_36dp.xml index 4d964871e..145abfc94 100644 --- a/app/src/main/res/drawable/type_add_color_36dp.xml +++ b/app/src/main/res/drawable/type_add_color_36dp.xml @@ -1,5 +1,5 @@ <vector android:autoMirrored="true" android:height="36dp" - android:tint="#00D400" android:viewportHeight="24.0" + android:tint="@color/activity_create" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="36dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="#FF000000" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/> </vector> diff --git a/app/src/main/res/drawable/type_delete_color_36dp.xml b/app/src/main/res/drawable/type_delete_color_36dp.xml index 014bf20b8..3b2394fa0 100644 --- a/app/src/main/res/drawable/type_delete_color_36dp.xml +++ b/app/src/main/res/drawable/type_delete_color_36dp.xml @@ -1,5 +1,5 @@ <vector android:autoMirrored="true" android:height="36dp" - android:tint="#D40000" android:viewportHeight="24.0" + android:tint="@color/activity_delete" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="36dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="#FF000000" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/> </vector> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ac0dadf82..0692fb8d6 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -133,9 +133,9 @@ android:background="?attr/selectableItemBackgroundBorderless" android:contentDescription="@string/simple_filter" android:padding="12dp" - android:tint="?attr/colorAccent" android:tooltipText="@string/simple_filter" app:srcCompat="@drawable/ic_filter_list_white_24dp" + app:tint="?attr/colorAccent" tools:targetApi="o" /> <ImageView @@ -147,8 +147,8 @@ android:layout_marginBottom="12dp" android:contentDescription="@null" android:src="@drawable/circle_grey600_8dp" - android:tint="@color/defaultBrand" android:visibility="gone" + app:tint="@color/defaultBrand" tools:visibility="visible" /> </FrameLayout> @@ -160,11 +160,11 @@ android:background="?attr/selectableItemBackgroundBorderless" android:contentDescription="@string/action_archived_cards" android:padding="12dp" - android:tint="?attr/colorAccent" android:tooltipText="@string/action_archived_cards" android:translationX="12dp" android:visibility="gone" app:srcCompat="@drawable/ic_archive_white_24dp" + app:tint="?attr/colorAccent" tools:targetApi="o" tools:visibility="visible" /> </androidx.appcompat.widget.Toolbar> @@ -192,9 +192,9 @@ android:background="?attr/colorPrimary" android:contentDescription="@string/add_list" android:foreground="?attr/selectableItemBackgroundBorderless" - android:tint="?attr/colorAccent" android:tooltipText="@string/manage_list" app:srcCompat="@drawable/ic_menu" + app:tint="?attr/colorAccent" tools:ignore="UnusedAttribute" /> </LinearLayout> diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index cf90f44c6..593570303 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Darrer compte</string> <string name="drawer_manage_accounts">Gestiona els comptes</string> - <!-- Simple values --> <string name="simple_boards">Taulells</string> <string name="simple_add">Afegeix</string> <string name="simple_save">Desa</string> @@ -45,7 +44,6 @@ <string name="delete_board">Suprimeix el tauler</string> <string name="delete_something">Elimina %1$s</string> - <!-- About --> <string name="about">Quant a</string> <string name="about_version_title">Versió</string> <string name="about_version">Esteu fent servir %1$s</string> @@ -166,11 +164,9 @@ <string name="open_in_browser">Obre al navegador</string> <string name="updating_card">S\'està actualitzant la targeta...</string> - <!-- Move lists --> <string name="move_list_right">Mou la llista a la dreta</string> <string name="move_list_left">Mou la llista a l\'esquerra</string> - <!-- Filter --> <string name="filter_no_filter">Totes</string> <string name="filter_overdue">Endarrerit</string> <string name="filter_today">Avui</string> @@ -181,7 +177,6 @@ <string name="filter_by_assigned_user">Filtra per usuari assignat</string> <string name="filter_by_duedate">Filtra per data de venciment</string> - <!-- Archived cards --> <string name="archived_cards">Targetes arxivades</string> <string name="action_card_dearchive">Desfés l\'arxivament de la targeta</string> <string name="action_archived_cards">Navega per les targetes arxivades</string> @@ -196,11 +191,9 @@ <string name="filter_user_title">Usuaris</string> <string name="filter_duedate_title">Data de venciment</string> - <!-- Archived boards --> <string name="action_board_dearchive">Desfés l\'arxivament del tauler</string> <string name="archived_boards">Taulers arxivats</string> - <!-- Errors --> <string name="error">S\'ha produït un error</string> <string name="synchronization_failed">Ha fallat la sincronització</string> <string name="operation_not_yet_supported">Encara no està suportat</string> diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 170d1a877..07f9eb0f3 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Poslední účet</string> <string name="drawer_manage_accounts">Spravovat účty</string> - <!-- Simple values --> <string name="simple_boards">Tabule</string> <string name="simple_add">Přidat</string> <string name="simple_save">Uložit</string> @@ -45,7 +44,6 @@ <string name="delete_board">Smazat tabuli</string> <string name="delete_something">Smazat %1$s</string> - <!-- About --> <string name="about">O aplikaci</string> <string name="about_version_title">Verze</string> <string name="about_version">Nyní používáte %1$s</string> @@ -171,11 +169,9 @@ <string name="open_in_browser">Otevřít v prohlížeči</string> <string name="updating_card">Aktualizace karty…</string> - <!-- Move lists --> <string name="move_list_right">Přesunout seznam vpravo</string> <string name="move_list_left">Přesunout seznam vlevo</string> - <!-- Filter --> <string name="filter_no_filter">Vše</string> <string name="filter_overdue">Po termínu</string> <string name="filter_today">Dnes</string> @@ -186,7 +182,6 @@ <string name="filter_by_assigned_user">Filtrovat podle uživatele, který je úkolem pověřen</string> <string name="filter_by_duedate">Filtrovat podle termínu</string> - <!-- Archived cards --> <string name="archived_cards">Archivované karty</string> <string name="action_card_dearchive">Vzít zpět archivaci karty</string> <string name="action_archived_cards">Procházet archivované karty</string> @@ -201,11 +196,9 @@ <string name="filter_user_title">Uživatelé</string> <string name="filter_duedate_title">Datum termínu</string> - <!-- Archived boards --> <string name="action_board_dearchive">Vzít zpět archivaci tabule</string> <string name="archived_boards">Archivované tabule</string> - <!-- Errors --> <string name="error">Objevila se chyba</string> <string name="synchronization_failed">Synchronizace se nezdařila</string> <string name="operation_not_yet_supported">Zatím nepodorováno</string> @@ -301,4 +294,13 @@ <string name="take_photo">Vyfotit</string> <string name="take_photo_switch_camera">Přepnout kameru</string> <string name="take_photo_toggle_torch">Vyp/zap. přisvícení</string> + <string name="show_all_contacts">Zobrazit všechny kontakty</string> + <string name="show_all_files">Zobrazit všechny soubory</string> + <string name="recent">Nedávné</string> + <string name="upload_a_new_attachment">Nahrát novou přílohu</string> + <string name="contacts">Kontakty</string> + <string name="downloads">Stažené</string> + <string name="files">Soubory</string> + <string name="gallery">Galerie</string> + <string name="simple_attach">přiložit</string> </resources> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 832518a18..053b042e8 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Letztes Konto</string> <string name="drawer_manage_accounts">Konten verwalten</string> - <!-- Simple values --> <string name="simple_boards">Boards</string> <string name="simple_add">Hinzufügen</string> <string name="simple_save">Speichern</string> @@ -45,7 +44,6 @@ <string name="delete_board">Board löschen</string> <string name="delete_something">Lösche %1$s</string> - <!-- About --> <string name="about">Über</string> <string name="about_version_title">Version</string> <string name="about_version">Sie benutzen aktuell %1$s</string> @@ -167,11 +165,9 @@ <string name="open_in_browser">Im Browser öffnen</string> <string name="updating_card">Karte wird aktualisiert…</string> - <!-- Move lists --> <string name="move_list_right">Liste nach rechts schieben</string> <string name="move_list_left">Liste nach links schieben</string> - <!-- Filter --> <string name="filter_no_filter">Alle</string> <string name="filter_overdue">Überfällig</string> <string name="filter_today">Heute</string> @@ -182,7 +178,6 @@ <string name="filter_by_assigned_user">Nach zugewiesenem Benutzer filtern</string> <string name="filter_by_duedate">Nach Fälligkeitsdatum filtern</string> - <!-- Archived cards --> <string name="archived_cards">Archivierte Karten</string> <string name="action_card_dearchive">Karte archivieren rückgängig machen</string> <string name="action_archived_cards">Archivierte Karten durchsuchen</string> @@ -197,11 +192,9 @@ <string name="filter_user_title">Benutzer</string> <string name="filter_duedate_title">Fälligkeitsdatum</string> - <!-- Archived boards --> <string name="action_board_dearchive">Board archivieren rückgängig machen</string> <string name="archived_boards">Archivierte Boards</string> - <!-- Errors --> <string name="error">Es ist ein Fehler aufgetreten</string> <string name="synchronization_failed">Synchronisierung fehlgeschlagen</string> <string name="operation_not_yet_supported">Wird bislang noch nicht unterstützt</string> @@ -277,7 +270,7 @@ <item quantity="one">%1$d Ressource</item> <item quantity="other">%1$d Ressourcen</item> </plurals> - <string name="no_assigned_label">Keine Schlagwort zugewiesen</string> + <string name="no_assigned_label">Kein Schlagwort zugewiesen</string> <string name="single_card">Einzelne Karte</string> <string name="project_type_room">Talk-Raum</string> <string name="simple_move">Verschieben</string> @@ -302,4 +295,5 @@ <string name="files">Dateien</string> <string name="gallery">Galerie</string> <string name="simple_attach">anhängen</string> + <string name="add_stack_widget">Ein Listen-Widget hinzufügen</string> </resources> diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 877578f2d..5afd6e1f6 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Τελευταίος λογαριασμός</string> <string name="drawer_manage_accounts">Διαχείριση λογαριασμών</string> - <!-- Simple values --> <string name="simple_boards">Πίνακες</string> <string name="simple_add">Προσθήκη</string> <string name="simple_save">Αποθήκευση</string> @@ -45,7 +44,6 @@ <string name="delete_board">Διαγραφή πίνακα</string> <string name="delete_something">Διαγραφή %1$s</string> - <!-- About --> <string name="about">Περί</string> <string name="about_version_title">Έκδοση</string> <string name="about_version">Προς το παρόν χρησιμοποιείτε %1$s</string> @@ -166,11 +164,9 @@ <string name="open_in_browser">Άνοιγμα στον περιηγητή ιστού</string> <string name="updating_card">Ενημέρωση καρτέλας...</string> - <!-- Move lists --> <string name="move_list_right">Μετακίνηση λίστας δεξιά</string> <string name="move_list_left">Μετακίνηση λίστας αριστερά</string> - <!-- Filter --> <string name="filter_no_filter">\'Ολα</string> <string name="filter_overdue">Εκπρόθεσμος</string> <string name="filter_today">Σήμερα</string> @@ -181,7 +177,6 @@ <string name="filter_by_assigned_user">Φίλτρο ανά χρήστη</string> <string name="filter_by_duedate">Φίλτρο ανά ημερομηνία λήξης</string> - <!-- Archived cards --> <string name="archived_cards">Αρχειοθετημένες κάρτες</string> <string name="action_card_dearchive">Αναίρεση αρχειοθέτησης κάρτας</string> <string name="action_archived_cards">Περιήγηση στις αρχειοθετημένες καρτέλες</string> @@ -196,11 +191,9 @@ <string name="filter_user_title">Χρήστες</string> <string name="filter_duedate_title">Προθεσμία</string> - <!-- Archived boards --> <string name="action_board_dearchive">Αναίρεση αρχειοθέτησης πίνακα</string> <string name="archived_boards">Αρχειοθέτηση πινάκων </string> - <!-- Errors --> <string name="error">Παρουσιάστηκε σφάλμα</string> <string name="synchronization_failed">Αποτυχία συγχρονισμού</string> <string name="operation_not_yet_supported">Δεν υποστηρίζεται ακόμη</string> diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index a54158ba9..763c1f02f 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Última cuenta</string> <string name="drawer_manage_accounts">Gestionar cuentas</string> - <!-- Simple values --> <string name="simple_boards">Tableros</string> <string name="simple_add">Añadir</string> <string name="simple_save">Guardar</string> @@ -45,7 +44,6 @@ <string name="delete_board">Eliminar tablero</string> <string name="delete_something">Borrar %1$s</string> - <!-- About --> <string name="about">Acerca de</string> <string name="about_version_title">Version</string> <string name="about_version">Actualmente estás usando %1$s</string> @@ -167,11 +165,9 @@ <string name="open_in_browser">Abrir en navegador</string> <string name="updating_card">Actualizando tarjeta</string> - <!-- Move lists --> <string name="move_list_right">Mover lista a la derecha</string> <string name="move_list_left">Mover lista a la izquierda</string> - <!-- Filter --> <string name="filter_no_filter">Todo</string> <string name="filter_overdue">Demorado</string> <string name="filter_today">Hoy</string> @@ -182,7 +178,6 @@ <string name="filter_by_assigned_user">Filtrar por usuario asignado</string> <string name="filter_by_duedate">Filtrar por fecha de finalización</string> - <!-- Archived cards --> <string name="archived_cards">Tarjetas archivadas</string> <string name="action_card_dearchive">Deshacer archivado de tarjeta</string> <string name="action_archived_cards">Explorar las tarjetas archivadas</string> @@ -197,11 +192,9 @@ <string name="filter_user_title">Usuarios</string> <string name="filter_duedate_title">Fecha de fin</string> - <!-- Archived boards --> <string name="action_board_dearchive">Deshacer archivado del tablero</string> <string name="archived_boards">Tableros archivados</string> - <!-- Errors --> <string name="error">Ha aparecido un error</string> <string name="synchronization_failed">Fallo en la sincronización</string> <string name="operation_not_yet_supported">No está soportado todavía</string> @@ -302,4 +295,5 @@ <string name="files">Archivos</string> <string name="gallery">Galería</string> <string name="simple_attach">adjuntar</string> + <string name="add_stack_widget">Agregar lista de widget</string> </resources> diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 283d409a3..6a7460eb9 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Azken kontua</string> <string name="drawer_manage_accounts">Kudeatu kontuak</string> - <!-- Simple values --> <string name="simple_boards">Mahaiak</string> <string name="simple_add">Gehitu</string> <string name="simple_save">Gorde</string> @@ -45,7 +44,6 @@ <string name="delete_board">Ezabatu mahaia</string> <string name="delete_something">Ezabatu %1$s</string> - <!-- About --> <string name="about">Honi buruz</string> <string name="about_version_title">Bertsioa</string> <string name="about_version">%1$s erabiltzen ari zara</string> @@ -166,11 +164,9 @@ <string name="open_in_browser">Ireki nabigatzailean</string> <string name="updating_card">Txartela eguneratzen...</string> - <!-- Move lists --> <string name="move_list_right">Mugitu zerrenda eskuinera</string> <string name="move_list_left">Mugitu zerrenda ezkerrera</string> - <!-- Filter --> <string name="filter_no_filter">Denak</string> <string name="filter_overdue">Atzeratuta</string> <string name="filter_today">Gaur</string> @@ -181,7 +177,6 @@ <string name="filter_by_assigned_user">Iragazi esleitutako erabiltzailez</string> <string name="filter_by_duedate">Iragazi epe-mugaz</string> - <!-- Archived cards --> <string name="archived_cards">Artxibatutako txartelak</string> <string name="action_card_dearchive">Desegin txartelak artxibatzea</string> <string name="action_archived_cards">Arakatu artxibatutako txartelak</string> @@ -196,11 +191,9 @@ <string name="filter_user_title">Erabiltzaileak</string> <string name="filter_duedate_title">Epe-muga</string> - <!-- Archived boards --> <string name="action_board_dearchive">Desegin mahaia artxibatzea</string> <string name="archived_boards">Artxibatutako mahaiak</string> - <!-- Errors --> <string name="error">Errore bat agertu da</string> <string name="synchronization_failed">Sinkronizazioak huts egin du</string> <string name="operation_not_yet_supported">Oraingoz ez da onartzen</string> diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml index 02d5c3423..088be8c83 100644 --- a/app/src/main/res/values-fi-rFI/strings.xml +++ b/app/src/main/res/values-fi-rFI/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Viimeisin tili</string> <string name="drawer_manage_accounts">Tilien hallinta</string> - <!-- Simple values --> <string name="simple_boards">Taulut</string> <string name="simple_add">Lisää</string> <string name="simple_save">Tallenna</string> @@ -45,7 +44,6 @@ <string name="delete_board">Poista taulu</string> <string name="delete_something">Poista %1$s</string> - <!-- About --> <string name="about">Tietoja</string> <string name="about_version_title">Versio</string> <string name="about_version">Käytössäsi on %1$s</string> @@ -166,11 +164,9 @@ <string name="open_in_browser">Avaa selaimessa</string> <string name="updating_card">Päivitetään korttia...</string> - <!-- Move lists --> <string name="move_list_right">Siirrä lista oikealle</string> <string name="move_list_left">Siirrä lista vasemmalle</string> - <!-- Filter --> <string name="filter_no_filter">Kaikki</string> <string name="filter_overdue">Myöhässä</string> <string name="filter_today">Tänään</string> @@ -181,7 +177,6 @@ <string name="filter_by_assigned_user">Suodata määritetyn käyttäjän mukaan</string> <string name="filter_by_duedate">Suodata määräpäivän mukaan</string> - <!-- Archived cards --> <string name="archived_cards">Arkistoidut kortit</string> <string name="action_card_dearchive">Kumoa kortin arkistointi</string> <string name="action_archived_cards">Selaa arkistoituja kortteja</string> @@ -196,11 +191,9 @@ <string name="filter_user_title">Käyttäjät</string> <string name="filter_duedate_title">Eräpäivä</string> - <!-- Archived boards --> <string name="action_board_dearchive">Kumoa taulun arkistointi</string> <string name="archived_boards">Arkistoidut taulut</string> - <!-- Errors --> <string name="error">Tapahtui virhe</string> <string name="synchronization_failed">Synkronointi epäonnistui</string> <string name="operation_not_yet_supported">Ei vielä tuettu</string> diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index c1820e9e8..c98042618 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Dernier compte</string> <string name="drawer_manage_accounts">Gérer les comptes</string> - <!-- Simple values --> <string name="simple_boards">Tableaux</string> <string name="simple_add">Ajouter</string> <string name="simple_save">Enregistrer</string> @@ -45,7 +44,6 @@ <string name="delete_board">Supprimer le tableau</string> <string name="delete_something">Supprimer %1$s</string> - <!-- About --> <string name="about">À propos de</string> <string name="about_version_title">Version</string> <string name="about_version">Vous utilisez actuellement la version : %1$s</string> @@ -167,11 +165,9 @@ <string name="open_in_browser">Ouvrir dans le navigateur web</string> <string name="updating_card">Mise à jour de la carte en cours...</string> - <!-- Move lists --> <string name="move_list_right">Déplacer la liste à droite</string> <string name="move_list_left">Déplacer la liste à gauche</string> - <!-- Filter --> <string name="filter_no_filter">Tout</string> <string name="filter_overdue">En retard</string> <string name="filter_today">Aujourd\'hui</string> @@ -182,7 +178,6 @@ <string name="filter_by_assigned_user">Filtrer par utilisateur assigné</string> <string name="filter_by_duedate">Filtrer par échéance</string> - <!-- Archived cards --> <string name="archived_cards">Cartes archivées</string> <string name="action_card_dearchive">Annuler l\'archivage de la carte</string> <string name="action_archived_cards">Parcourir les cartes archivées</string> @@ -197,11 +192,9 @@ <string name="filter_user_title">Utilisateurs</string> <string name="filter_duedate_title">Date d\'échéance</string> - <!-- Archived boards --> <string name="action_board_dearchive">Annuler l\'archivage du tableau</string> <string name="archived_boards">Tableaux archivés</string> - <!-- Errors --> <string name="error">Une erreur est survenue</string> <string name="synchronization_failed">Échec de synchronisation</string> <string name="operation_not_yet_supported">Non supporté actuellement</string> @@ -293,9 +286,14 @@ <string name="take_photo">Prendre une photo</string> <string name="take_photo_switch_camera">Changer d\'appareil photo</string> <string name="take_photo_toggle_torch">Allumer la lampe</string> + <string name="show_all_contacts">Afficher toutes les contacts</string> <string name="show_all_files">Afficher tous les fichiers</string> + <string name="recent">Récent</string> + <string name="upload_a_new_attachment">Envoyer une nouvelle pièce jointe</string> <string name="contacts">Contacts</string> <string name="downloads">Téléchargements</string> <string name="files">Fichiers</string> <string name="gallery">Galerie</string> - </resources> + <string name="simple_attach">joindre</string> + <string name="add_stack_widget">Ajouter un widget liste</string> +</resources> diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 515172758..2b8b7aaef 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Última conta</string> <string name="drawer_manage_accounts">Xestionar contas</string> - <!-- Simple values --> <string name="simple_boards">Taboleiros</string> <string name="simple_add">Engadir</string> <string name="simple_save">Gardar</string> @@ -45,7 +44,6 @@ <string name="delete_board">Eliminar taboleiro</string> <string name="delete_something">Eliminar %1$s</string> - <!-- About --> <string name="about">Sobre</string> <string name="about_version_title">Versión</string> <string name="about_version">Agora está a empregar %1$s</string> @@ -167,11 +165,9 @@ <string name="open_in_browser">Abrir no navegador</string> <string name="updating_card">Actualizado tarxeta…</string> - <!-- Move lists --> <string name="move_list_right">Mover a lista á dereita</string> <string name="move_list_left">Mover a lista á esquerda</string> - <!-- Filter --> <string name="filter_no_filter">Todo</string> <string name="filter_overdue">Caducado</string> <string name="filter_today">Hoxe</string> @@ -182,7 +178,6 @@ <string name="filter_by_assigned_user">Filtrar polo usuario asignado</string> <string name="filter_by_duedate">Filtrar pola data de caducidade</string> - <!-- Archived cards --> <string name="archived_cards">Tarxetas arquivadas</string> <string name="action_card_dearchive">Desfacer o arquivo de tarxetas</string> <string name="action_archived_cards">Examinar as tarxetas arquivadas</string> @@ -197,11 +192,9 @@ <string name="filter_user_title">Usuarios</string> <string name="filter_duedate_title">Data de caducidade</string> - <!-- Archived boards --> <string name="action_board_dearchive">Desfacer o arquivo de taboleiros</string> <string name="archived_boards">Taboleiros arquivados</string> - <!-- Errors --> <string name="error">Apareceu un erro</string> <string name="synchronization_failed">Produciuse un fallo na sincronización</string> <string name="operation_not_yet_supported">Aínda non está admitido</string> @@ -302,4 +295,5 @@ <string name="files">Ficheiros</string> <string name="gallery">Galería</string> <string name="simple_attach">anexar</string> + <string name="add_stack_widget">Engadir o trebello de lista</string> </resources> diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index afd2d349e..366e55de1 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">חשבון אחרון</string> <string name="drawer_manage_accounts">ניהול חשבונות</string> - <!-- Simple values --> <string name="simple_boards">לוחות</string> <string name="simple_add">הוספה</string> <string name="simple_save">שמור</string> @@ -43,7 +42,6 @@ <string name="delete_board">מחק לוח</string> <string name="delete_something">מחיקת %1$s</string> - <!-- About --> <string name="about">על אודות</string> <string name="about_version_title">גרסה</string> <string name="about_version">אתה משתמש כרגע ב%1$s</string> @@ -166,11 +164,9 @@ <string name="open_in_browser">פתיחה בדפדפן</string> <string name="updating_card">הכרטיס מעודכן…</string> - <!-- Move lists --> <string name="move_list_right">העברת רשימה ימינה</string> <string name="move_list_left">העברת רשימה שמאלה</string> - <!-- Filter --> <string name="filter_no_filter">הכול</string> <string name="filter_overdue">באיחור</string> <string name="filter_today">היום</string> @@ -181,7 +177,6 @@ <string name="filter_by_assigned_user">סינון לפי משתמש מוקצה</string> <string name="filter_by_duedate">סינון לפי תאריך יעד</string> - <!-- Archived cards --> <string name="archived_cards">כרטיסים בארכיון</string> <string name="action_card_dearchive">ביטול העברת כרטיס לארכיון</string> <string name="action_archived_cards">עיון בכרטיסים בארכיון</string> @@ -196,11 +191,9 @@ <string name="filter_user_title">משתמשים</string> <string name="filter_duedate_title">תאריך יעד</string> - <!-- Archived boards --> <string name="action_board_dearchive">ביטול העברת הלוח לארכיון</string> <string name="archived_boards">לוחות שנשמרו בארכיון</string> - <!-- Errors --> <string name="error">הופיעה שגיאה</string> <string name="synchronization_failed">הסנכרון נכשל</string> <string name="operation_not_yet_supported">אין תמיכה עדיין</string> diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 76875b14d..edd334cf3 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Prethodni račun</string> <string name="drawer_manage_accounts">Upravljaj računima</string> - <!-- Simple values --> <string name="simple_boards">Ploče</string> <string name="simple_add">Dodaj</string> <string name="simple_save">Spremi</string> @@ -45,7 +44,6 @@ <string name="delete_board">Izbriši ploču</string> <string name="delete_something">Izbriši %1$s</string> - <!-- About --> <string name="about">Informacije</string> <string name="about_version_title">Inačica</string> <string name="about_version">Trenutno se koristite %1$s</string> @@ -168,11 +166,9 @@ <string name="open_in_browser">Otvori u pregledniku</string> <string name="updating_card">Ažuriranje kartice…</string> - <!-- Move lists --> <string name="move_list_right">Pomakni popis desno</string> <string name="move_list_left">Pomakni popis lijevo</string> - <!-- Filter --> <string name="filter_no_filter">Sve</string> <string name="filter_overdue">Kasni</string> <string name="filter_today">Danas</string> @@ -183,7 +179,6 @@ <string name="filter_by_assigned_user">Filtriraj prema dodijeljenom korisniku</string> <string name="filter_by_duedate">Filtriraj prema datumu dospijeća</string> - <!-- Archived cards --> <string name="archived_cards">Arhivirane kartice</string> <string name="action_card_dearchive">Poništi arhiviranje kartice</string> <string name="action_archived_cards">Pretraži arhivirane kartice</string> @@ -198,11 +193,9 @@ <string name="filter_user_title">Korisnici</string> <string name="filter_duedate_title">Datum dospijeća</string> - <!-- Archived boards --> <string name="action_board_dearchive">Poništi arhiviranje ploče</string> <string name="archived_boards">Arhivirane ploče</string> - <!-- Errors --> <string name="error">Pojavila se pogreška</string> <string name="synchronization_failed">Sinkronizacija nije uspjela</string> <string name="operation_not_yet_supported">Još nije podržano</string> diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index 29007d971..e6f882727 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Utolsó fiók</string> <string name="drawer_manage_accounts">Fiókok kezelése</string> - <!-- Simple values --> <string name="simple_boards">Táblák</string> <string name="simple_add">Hozzáadás</string> <string name="simple_save">Mentés</string> @@ -45,7 +44,6 @@ <string name="delete_board">Tábla törlése</string> <string name="delete_something">%1$s törlése</string> - <!-- About --> <string name="about">Névjegy</string> <string name="about_version_title">Verzió</string> <string name="about_version">Jelenleg ezt a verziót használja: %1$s</string> @@ -167,11 +165,9 @@ <string name="open_in_browser">Megnyitás böngészőben</string> <string name="updating_card">Kártya frissítése…</string> - <!-- Move lists --> <string name="move_list_right">Lista áthelyezése jobbra</string> <string name="move_list_left">Lista áthelyezése balra</string> - <!-- Filter --> <string name="filter_no_filter">Mind</string> <string name="filter_overdue">Lejárt</string> <string name="filter_today">Ma</string> @@ -182,7 +178,6 @@ <string name="filter_by_assigned_user">Szűrés hozzárendelt felhasználó szerint</string> <string name="filter_by_duedate">Szűrés határidő szerint</string> - <!-- Archived cards --> <string name="archived_cards">Archivált kártyák</string> <string name="action_card_dearchive">Kártya archiválásának visszavonása</string> <string name="action_archived_cards">Archivált kártyák tallózása</string> @@ -197,11 +192,9 @@ <string name="filter_user_title">Felhasználók</string> <string name="filter_duedate_title">Határidő</string> - <!-- Archived boards --> <string name="action_board_dearchive">Tábla archiválásának visszavonása</string> <string name="archived_boards">Archivált táblák</string> - <!-- Errors --> <string name="error">Hiba történt</string> <string name="synchronization_failed">Szinkronizálás sikertelen</string> <string name="operation_not_yet_supported">Még nem támogatott</string> @@ -286,4 +279,5 @@ <string name="simple_clone">Klónozás</string> <string name="user_avatar">Felhasználói avatar</string> <string name="simple_unassign">Elvétel</string> - </resources> + <string name="add_stack_widget">Lista felületi elem hozzáadása</string> +</resources> diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index ac9f496f1..a971fa004 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Ultimo account</string> <string name="drawer_manage_accounts">Gestisci account</string> - <!-- Simple values --> <string name="simple_boards">Lavagne</string> <string name="simple_add">Aggiungi</string> <string name="simple_save">Salva</string> @@ -45,7 +44,6 @@ <string name="delete_board">Elimina lavagna</string> <string name="delete_something">Elimina %1$s</string> - <!-- About --> <string name="about">Informazioni</string> <string name="about_version_title">Versione</string> <string name="about_version">Stai utilizzando attualmente %1$s</string> @@ -167,11 +165,9 @@ <string name="open_in_browser">Apri nel browser</string> <string name="updating_card">Aggiornamento scheda...</string> - <!-- Move lists --> <string name="move_list_right">Sposta a destra l\'elenco</string> <string name="move_list_left">Sposta a sinistra l\'elenco</string> - <!-- Filter --> <string name="filter_no_filter">Tutti</string> <string name="filter_overdue">Scadenza</string> <string name="filter_today">Oggi</string> @@ -182,7 +178,6 @@ <string name="filter_by_assigned_user">Filtra per utente assegnato</string> <string name="filter_by_duedate">Filtra per data di scadenza</string> - <!-- Archived cards --> <string name="archived_cards">Schede archiviate</string> <string name="action_card_dearchive">Annulla archiviazione della scheda</string> <string name="action_archived_cards">Sfoglia le schede archiviate</string> @@ -197,11 +192,9 @@ <string name="filter_user_title">Utenti</string> <string name="filter_duedate_title">Data di scadenza</string> - <!-- Archived boards --> <string name="action_board_dearchive">Annulla archiviazione della lavagna</string> <string name="archived_boards">Lavagne archiviate</string> - <!-- Errors --> <string name="error">Si è verificato un errore</string> <string name="synchronization_failed">Sincronizzazione non riuscita</string> <string name="operation_not_yet_supported">Non ancora supportato</string> @@ -302,4 +295,5 @@ <string name="files">File</string> <string name="gallery">Galleria</string> <string name="simple_attach">allega</string> + <string name="add_stack_widget">Aggiungi widget elenco</string> </resources> diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index f66d29f15..57642a08e 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">最後のアカウント</string> <string name="drawer_manage_accounts">アカウント管理</string> - <!-- Simple values --> <string name="simple_boards">ボード</string> <string name="simple_add">追加</string> <string name="simple_save">保存</string> @@ -45,7 +44,6 @@ <string name="delete_board">ボードを削除</string> <string name="delete_something">%1$sを削除</string> - <!-- About --> <string name="about">バージョン情報</string> <string name="about_version_title">バージョン</string> <string name="about_version">現在%1$sを使用しています</string> @@ -111,6 +109,7 @@ <string name="no_lists_yet">まだリストがありません</string> <string name="do_you_want_to_save_your_changes">変更を保存しますか?</string> <string name="do_you_want_to_archive_all_cards_of_the_list">%1$s の全カードをアーカイブしますか?</string> + <string name="do_you_want_to_archive_all_cards_of_the_filtered_list">%1$s のフィルターされた全カードをアーカイブしますか?</string> <plurals name="do_you_want_to_delete_the_current_list"> <item quantity="other">このリストの%1$dのカードすべてが完全に削除されます。</item> </plurals> @@ -164,11 +163,9 @@ <string name="open_in_browser">ブラウザーで開く</string> <string name="updating_card">カードの更新中...</string> - <!-- Move lists --> <string name="move_list_right">リストを右に移動</string> <string name="move_list_left">リストを左に移動</string> - <!-- Filter --> <string name="filter_no_filter">すべて</string> <string name="filter_overdue">期限超過</string> <string name="filter_today">今日</string> @@ -179,7 +176,6 @@ <string name="filter_by_assigned_user">割当ユーザーでフィルター</string> <string name="filter_by_duedate">期限でフィルター</string> - <!-- Archived cards --> <string name="archived_cards">カードをアーカイブ</string> <string name="action_card_dearchive">カードのアーカイブを元に戻す</string> <string name="action_archived_cards">アーカイブされたカードをブラウズする</string> @@ -194,11 +190,9 @@ <string name="filter_user_title">ユーザー</string> <string name="filter_duedate_title">期限</string> - <!-- Archived boards --> <string name="action_board_dearchive">ボードのアーカイブを元に戻す</string> <string name="archived_boards">アーカイブ済みのボード</string> - <!-- Errors --> <string name="error">エラーが見つかりました</string> <string name="synchronization_failed">同期に失敗</string> <string name="operation_not_yet_supported">未サポート</string> @@ -278,4 +272,25 @@ <string name="project_type_room">トークルーム</string> <string name="simple_move">移動</string> <string name="cannot_upload_files_without_permission">権限が無いためアップロードできません</string> - </resources> + <string name="clone_cards">カードを複製</string> + <string name="simple_clone">複製</string> + <string name="user_avatar">ユーザーのアバター</string> + <string name="simple_unassign">割り当てを解除</string> + <string name="simple_contact">連絡先</string> + <string name="simple_file">ファイル</string> + <string name="simple_camera">カメラ</string> + <string name="min_api_21">この機能には少なくともAndroid5以上が必要です。</string> + <string name="take_photo">写真を撮る</string> + <string name="take_photo_switch_camera">カメラ切替</string> + <string name="take_photo_toggle_torch">フラッシュを切替</string> + <string name="show_all_contacts">すべての連絡先を表示</string> + <string name="show_all_files">すべてのファイルを表示</string> + <string name="recent">最近</string> + <string name="upload_a_new_attachment">新しい添付をアップロードする</string> + <string name="contacts">連絡先</string> + <string name="downloads">ダウンロード</string> + <string name="files">ファイル</string> + <string name="gallery">ギャラリー</string> + <string name="simple_attach">参加</string> + <string name="add_stack_widget">リストのウィジェットを追加</string> +</resources> diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 2163e68f6..da6a79cdc 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">마지막 계정</string> <string name="drawer_manage_accounts">계정 관리</string> - <!-- Simple values --> <string name="simple_boards">게시판</string> <string name="simple_add">추가</string> <string name="simple_save">저장</string> @@ -45,7 +44,6 @@ <string name="delete_board">게시판 삭제</string> <string name="delete_something">%1$s 삭제</string> - <!-- About --> <string name="about">정보</string> <string name="about_version_title">버전</string> <string name="about_version"> 현재 %1$s사용 중</string> @@ -111,6 +109,7 @@ <string name="no_lists_yet">리스트 없음</string> <string name="do_you_want_to_save_your_changes">변경된 사항을 저장하시겠습니까?</string> <string name="do_you_want_to_archive_all_cards_of_the_list">모든 %1$s카드들을 보관 하시겠습니까?</string> + <string name="do_you_want_to_archive_all_cards_of_the_filtered_list">필터링된 %1$s 카드를 모두 보관하시겠습니까?</string> <plurals name="do_you_want_to_delete_the_current_list"> <item quantity="other">이 리스트의 모든 %1$d카드가 영구적으로 지워집니다.</item> </plurals> @@ -164,11 +163,9 @@ <string name="open_in_browser">브라우저에서 열기</string> <string name="updating_card">카드 업데이트 중...</string> - <!-- Move lists --> <string name="move_list_right">리스트를 오른쪽으로 옮기기</string> <string name="move_list_left">리스트를 왼쪽으로 옮기기</string> - <!-- Filter --> <string name="filter_no_filter">모두</string> <string name="filter_overdue">기한 넘김</string> <string name="filter_today">오늘</string> @@ -179,7 +176,6 @@ <string name="filter_by_assigned_user">지정된 사용자로 필터링</string> <string name="filter_by_duedate">기한으로 필터링</string> - <!-- Archived cards --> <string name="archived_cards">보관된 카드들</string> <string name="action_card_dearchive">카드 보관 되돌리기</string> <string name="action_archived_cards">보관된 카드 둘러보기</string> @@ -194,11 +190,9 @@ <string name="filter_user_title">사용자</string> <string name="filter_duedate_title">만료 날짜</string> - <!-- Archived boards --> <string name="action_board_dearchive">보드 보관 되돌리기</string> <string name="archived_boards">보관된 게시판</string> - <!-- Errors --> <string name="error">오류가 나타남</string> <string name="synchronization_failed">동기화에 실패했습니다.</string> <string name="operation_not_yet_supported">아직 지원되지 않습니다!</string> @@ -212,7 +206,7 @@ <string name="error_dialog_title">세상에 - 무슨일이야?</string> <string name="error_dialog_tip_token_mismatch_retry">앱을 종료하고 다시 시작해주십시오. 아마 Nextcloud에 잘못된 연결이 있었을 것입니다.</string> - <string name="error_dialog_tip_clear_storage_might_help">이슈가 지속되면 Nextcloud와 Nextcloud Deck라는 두 앱을 스토리지에서 지워 이 문제를 해결하십시오.ㅣ</string> + <string name="error_dialog_tip_clear_storage_might_help">이슈가 지속되면 Nextcloud와 Nextcloud Deck라는 두 앱을 스토리지에서 지워 이 문제를 해결하십시오.</string> <string name="error_dialog_tip_database_upgrade_failed">데이터베이스 업그레이드 실패. 오류를 보고하고 정상적인 앱사용을 위해 저장소를 정리하세요.</string> <string name="error_dialog_tip_clear_storage">저장공간을 비우기 위해 app info를 열고 Storage → Clear storage를 선택해주십시오.</string> <string name="error_dialog_tip_files_outdated">당신의 Nextcloud 앱은 예전 버전입니다. Play Store나 F-Droid에 가서 최신 버전을 다운로드 하십시오.</string> @@ -221,6 +215,17 @@ <string name="error_dialog_timeout_instance">서버로부터 응답이 없습니다. 당신의 인스턴스가 잘 작동하는지 확인해 주십시오.</string> <string name="error_dialog_timeout_toggle">네트워크 연결을 확인하십시오. 종종 모바일데이터나 와이파이를 껐다가 키는 것이 도움이 될 것입니다.</string> <string name="error_dialog_check_server">서버의 응답이 틀렸습니다. 덱에 접근할 수 있는지 웹인터페이스로 확인해 주세요.</string> + <string name="error_dialog_check_server_logs">Nextcloud 설정에 문제가 있습니다. 서버 로그 파일을 살펴보시기 바랍니다.</string> + <string name="error_dialog_check_maintenance">Nextcloud 인스턴스가 현재 유지 보수 모드에 있지 않은지 확인해 주세요.</string> + <string name="error_dialog_insufficient_storage">Nextcloud 인스턴스에 사용 가능한 스토리지가 남아 있지 않습니다. 클라우드에 로컬 변경사항을 동기화하려면 일부 파일을 삭제해 주십시오.</string> + <string name="error_dialog_we_need_info">귀하를 돕기 위해 다음 기술 정보가 필요합니다.</string> + <string name="error_dialog_redirect">서버가 HTTP 302 상태 코드로 응답했습니다. 이는 서버에 Deck 앱을 설치하지 않았거나 잘못 구성되었음을 의미합니다. 이 문제는 .htaccess 파일의 사용자 지정 재정의 또는 OID Client와 같은 Nextcloud 앱에서 발생할 수 있습니다.</string> + <string name="error_dialog_version_not_parsable">서버 측 Deck 앱의 버전을 확인할 수 없습니다. 설치 및 활성화되어 있는지 확인하십시오.</string> + <string name="error_dialog_account_might_not_be_authorized">Nextcloud 앱의 계정이 더 이상 인증되지 않을 수 있습니다.</string> + <string name="error_dialog_user_not_found_in_database">현재 사용자가 데이터베이스에 있는 사용자와 일치하지 않습니다. Nextcloud 인스턴스에서 LDAP을 사용하는 경우 Nextcloud 앱에 이전 사용자 ID가 저장되었을 수 있습니다.</string> + <string name="error_dialog_capabilities_not_parsable">서버의 기능을 가져올 수 없습니다. 서버가 제대로 실행되고 다른 클라이언트 앱이 Nextcloud에 액세스할 수 있는지 확인하십시오.</string> + <string name="error_dialog_attachment_upload_failed">첨부 파일을 업로드 할 수 없습니다. 다른 방법으로 공유하시고 저희에게 이 버그에 대해 알려주세요.</string> + <string name="error_dialog_tip_disable_battery_optimizations">Nextcloud 및 Deck 앱에 대한 모든 배터리 최적화를 비활성화해 주십시오.</string> <string name="error_action_open_deck_info">앱 정보 열기</string> <string name="error_action_open_network">네트워크 환경설정</string> <string name="error_action_server_logs">서버 기록</string> @@ -234,15 +239,57 @@ <string name="manage_accounts">계정 관리</string> <string name="manage_list">목록 관리</string> <string name="simple_reply">답장</string> + <string name="error_while_uploading_attachment">%1$s 첨부 파일을 업로드하는 동안 오류가 발생했습니다.</string> <string name="append_text_to_description">설명에 추가</string> <string name="add_text_as_comment">댓글로 추가하기</string> + <string name="progress_count">%2$d의 %1$d</string> + <plurals name="progress_error_count"> + <item quantity="other">업로드하는 동안 %1$d 오류가 발생했습니다.</item> + </plurals> <string name="simple_report">보고</string> <string name="error_action_open_battery_settings">배터리 설정</string> + <string name="move_warning">카드를 다른 보드로 옮길 때 댓글이나 첨부 파일을 전송할 수 없습니다.</string> <string name="clone_board">게시판 복제</string> <string name="cloning_board">%1$s 복제중...</string> <string name="successfully_cloned_board">%1$s이(가) 성공적으로 복제되었습니다.</string> + <string name="attachment_does_not_yet_exist">첨부 파일이 아직 Deck에 없습니다.</string> + <string name="card_does_not_yet_exist">카드가 아직 Deck에 없습니다.</string> + <string name="widget_stack_title">목록</string> + <string name="widget_stack_header_icon">위젯 헤더 아이콘</string> + <string name="widget_stack_placeholder_icon">위젯 자리 표시 아이콘</string> + <string name="select_stack">목록 선택</string> + <string name="project_type_deck_board">Deck 보드</string> + <string name="project_type_deck_card">Deck 카드</string> <string name="project_type_file">파일</string> <string name="projects_title">프로젝트</string> + <plurals name="resources_count"> + <item quantity="other">%1$d 자원</item> + </plurals> + <string name="no_assigned_label">할당된 태그 없음</string> + <string name="single_card">단일 카드</string> + <string name="project_type_room">대화방</string> <string name="simple_move">이동</string> - </resources> + <string name="cannot_upload_files_without_permission">권한 없이 파일을 업로드할 수 없습니다.</string> + <string name="clone_cards">복제 카드</string> + <string name="simple_clone">복제</string> + <string name="user_avatar">사용자 아바타</string> + <string name="simple_unassign">할당 해제</string> + <string name="simple_contact">연락처</string> + <string name="simple_file">파일</string> + <string name="simple_camera">카메라</string> + <string name="min_api_21">이 기능을 사용하려면 적어도 Android 5가 필요합니다.</string> + <string name="take_photo">사진 찍기</string> + <string name="take_photo_switch_camera">카메라 전환</string> + <string name="take_photo_toggle_torch">토치 전환</string> + <string name="show_all_contacts">모든 연락처 보기</string> + <string name="show_all_files">모든 파일 보기</string> + <string name="recent">최근 항목</string> + <string name="upload_a_new_attachment">새 첨부 파일 업로드</string> + <string name="contacts">연락처</string> + <string name="downloads">다운로드</string> + <string name="files">파일</string> + <string name="gallery">갤러리</string> + <string name="simple_attach">첨부하기</string> + <string name="add_stack_widget">목록 위젯 추가</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 57c999618..760e340c8 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Siste konto</string> <string name="drawer_manage_accounts">Håndter kontoer</string> - <!-- Simple values --> <string name="simple_boards">Tavler</string> <string name="simple_add">Legg til</string> <string name="simple_save">Lagre</string> @@ -45,7 +44,6 @@ <string name="delete_board">Slett tavle</string> <string name="delete_something">Slett %1$s</string> - <!-- About --> <string name="about">Om</string> <string name="about_version_title">Versjon</string> <string name="about_version">Du bruker forøyeblikket %1$s</string> @@ -166,11 +164,9 @@ <string name="open_in_browser">Åpne i nettleser</string> <string name="updating_card">Oppdaterer kort...</string> - <!-- Move lists --> <string name="move_list_right">Flytt listen til høyre</string> <string name="move_list_left">Flytt listen til venstre</string> - <!-- Filter --> <string name="filter_no_filter">Alle</string> <string name="filter_overdue">Utløpt</string> <string name="filter_today">I dag</string> @@ -181,7 +177,6 @@ <string name="filter_by_assigned_user">Filtrer på tildelt bruker</string> <string name="filter_by_duedate">Filtrer på forfallsdato</string> - <!-- Archived cards --> <string name="archived_cards">Arkiver tavle</string> <string name="action_card_dearchive">Angre arkivering av kort</string> <string name="action_archived_cards">Bla gjennom arkiverte kort</string> @@ -196,11 +191,9 @@ <string name="filter_user_title">Brukere</string> <string name="filter_duedate_title">Forfallsdato</string> - <!-- Archived boards --> <string name="action_board_dearchive">Angre arkivering av tavle</string> <string name="archived_boards">Arkiverte tavler</string> - <!-- Errors --> <string name="error">En feil oppstod</string> <string name="synchronization_failed">Synkronisering mislyktes</string> <string name="operation_not_yet_supported">Ikke støttet enda</string> diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 975ef99de..d931f8b20 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Laatste account</string> <string name="drawer_manage_accounts">Accounts beheren </string> - <!-- Simple values --> <string name="simple_boards">Bord</string> <string name="simple_add">Toevoegen</string> <string name="simple_save">Bewaren</string> @@ -45,7 +44,6 @@ <string name="delete_board">Bord verwijderen</string> <string name="delete_something">Verwijder %1$s</string> - <!-- About --> <string name="about">Over</string> <string name="about_version_title">Versie</string> <string name="about_version">Je gebruikt nu %1$s</string> @@ -166,11 +164,9 @@ <string name="open_in_browser">Open in browser</string> <string name="updating_card">Kaart wordt geüpdatet...</string> - <!-- Move lists --> <string name="move_list_right">Verplaats de stapel naar rechts</string> <string name="move_list_left">Verplaats de stapel naar links</string> - <!-- Filter --> <string name="filter_no_filter">Alle</string> <string name="filter_overdue">Vervallen</string> <string name="filter_today">Vandaag</string> @@ -181,7 +177,6 @@ <string name="filter_by_assigned_user">Filter op toegewezen gebruiker</string> <string name="filter_by_duedate">Filter op vervaldatum</string> - <!-- Archived cards --> <string name="archived_cards">Gearchiveerde kaarten</string> <string name="action_card_dearchive">Kaartarchivering ongedaan maken</string> <string name="action_archived_cards">Blader door gearchiveerde kaarten</string> @@ -196,11 +191,9 @@ <string name="filter_user_title">Gebruikers</string> <string name="filter_duedate_title">Vervaldatum</string> - <!-- Archived boards --> <string name="action_board_dearchive">Archiveren van bord ongedaan maken</string> <string name="archived_boards">Gearchiveerde borden</string> - <!-- Errors --> <string name="error">Er is een fout verschenen</string> <string name="synchronization_failed">Synchronisatie mislukt</string> <string name="operation_not_yet_supported">Nog niet ondersteund</string> diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 67af469be..626b4dacc 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Ostatnie konto</string> <string name="drawer_manage_accounts">Zarządzaj kontami</string> - <!-- Simple values --> <string name="simple_boards">Tablice</string> <string name="simple_add">Dodaj</string> <string name="simple_save">Zapisz</string> @@ -45,7 +44,6 @@ <string name="delete_board">Usuń tablicę</string> <string name="delete_something">Usuń %1$s</string> - <!-- About --> <string name="about">O aplikacji</string> <string name="about_version_title">Wersja</string> <string name="about_version">Aktualnie używasz %1$s</string> @@ -58,11 +56,11 @@ <string name="about_source_title">Kod źródłowy</string> <string name="about_source">Projekt jest hostowany na GitHub: %1$s</string> <string name="about_issues_title">Problemy</string> - <string name="about_issues">Możesz zgłaszać błędy, propozycje ulepszeń i prośby o funkcje na GitHub: %1$s</string> + <string name="about_issues">Możesz zgłaszać błędy, propozycje ulepszeń i prośby o funkcje w liście problemów na GitHub: %1$s</string> <string name="about_translate_title">Tłumaczyć</string> <string name="about_translate">Dołącz do zespołu Nextcloud na Transifex i pomóż nam przetłumaczyć tę aplikację: %1$s</string> <string name="about_app_license_title">Licencja</string> - <string name="about_app_license">Ta aplikacja jest licencjonowana na podstawie GNU GENERAL PUBLIC LICENSE v3+.</string> + <string name="about_app_license">Aplikacja jest na licencji GNU GENERAL PUBLIC LICENSE v3+.</string> <string name="about_app_license_button">Zobacz licencję</string> <string name="about_icons_disclaimer_title">Ikony</string> <string name="about_icons_disclaimer_app_icon">Oryginalna ikona. Zobacz %1$s.</string> @@ -171,11 +169,9 @@ <string name="open_in_browser">Otwórz w przeglądarce</string> <string name="updating_card">Aktualizowanie karty…</string> - <!-- Move lists --> <string name="move_list_right">Przesuń listę w prawo</string> <string name="move_list_left">Przesuń listę w lewo</string> - <!-- Filter --> <string name="filter_no_filter">Wszystko</string> <string name="filter_overdue">Zaległe</string> <string name="filter_today">Dzisiaj</string> @@ -186,7 +182,6 @@ <string name="filter_by_assigned_user">Filtruj według przypisanego użytkownika</string> <string name="filter_by_duedate">Filtruj według terminu</string> - <!-- Archived cards --> <string name="archived_cards">Zarchiwizowane karty</string> <string name="action_card_dearchive">Cofnij archiwizację karty</string> <string name="action_archived_cards">Przeglądaj zarchiwizowane karty</string> @@ -201,11 +196,9 @@ <string name="filter_user_title">Użytkownicy</string> <string name="filter_duedate_title">Data realizacji</string> - <!-- Archived boards --> <string name="action_board_dearchive">Cofnij archiwizację tablicy</string> <string name="archived_boards">Zarchiwizowane tablice</string> - <!-- Errors --> <string name="error">Wystąpił błąd</string> <string name="synchronization_failed">Synchronizacja nie powiodła się</string> <string name="operation_not_yet_supported">Jeszcze nie obsługiwane</string> @@ -310,4 +303,5 @@ <string name="files">Pliki</string> <string name="gallery">Galeria</string> <string name="simple_attach">dołącz</string> + <string name="add_stack_widget">Dodaj widżet listy</string> </resources> diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index c88975abb..a20656dd1 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Última conta</string> <string name="drawer_manage_accounts">Gerenciar contas</string> - <!-- Simple values --> <string name="simple_boards">Painéis</string> <string name="simple_add">Adicionar</string> <string name="simple_save">Salvar</string> @@ -45,7 +44,6 @@ <string name="delete_board">Excluir painel</string> <string name="delete_something">Excluir %1$s</string> - <!-- About --> <string name="about">Sobre</string> <string name="about_version_title">Versão</string> <string name="about_version">Atualmente você está usando %1$s</string> @@ -167,11 +165,9 @@ <string name="open_in_browser">Abrir no navegador</string> <string name="updating_card">Atualizando cartão...</string> - <!-- Move lists --> <string name="move_list_right">Mover lista para a direita</string> <string name="move_list_left">Mover lista para a esquerda</string> - <!-- Filter --> <string name="filter_no_filter">Tudo</string> <string name="filter_overdue">Vencidos</string> <string name="filter_today">Hoje</string> @@ -182,7 +178,6 @@ <string name="filter_by_assigned_user">Filtrar por usuário atribuído</string> <string name="filter_by_duedate">Filtrar por data de vencimento</string> - <!-- Archived cards --> <string name="archived_cards">Cartões arquivados</string> <string name="action_card_dearchive">Desfazer arquivamento do cartão</string> <string name="action_archived_cards">Navegar pelos cartões arquivados</string> @@ -197,11 +192,9 @@ <string name="filter_user_title">Usuários</string> <string name="filter_duedate_title">Data de vencimento</string> - <!-- Archived boards --> <string name="action_board_dearchive">Desfazer arquivamento do painel</string> <string name="archived_boards">Painéis arquivados</string> - <!-- Errors --> <string name="error">Ocorreu um erro</string> <string name="synchronization_failed">A sincronização falhou</string> <string name="operation_not_yet_supported">Ainda não suportado</string> diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d2491bc65..bd5a1dd6b 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Последняя учётная запись</string> <string name="drawer_manage_accounts">Управление аккаунтами</string> - <!-- Simple values --> <string name="simple_boards">Доски</string> <string name="simple_add">Добавить</string> <string name="simple_save">Сохранить</string> @@ -45,7 +44,6 @@ <string name="delete_board">Удалить доску</string> <string name="delete_something">Удалить %1$s</string> - <!-- About --> <string name="about">О программе</string> <string name="about_version_title">Версия</string> <string name="about_version">Вы используете %1$s</string> @@ -111,6 +109,7 @@ <string name="no_lists_yet">Нет ни одного списка</string> <string name="do_you_want_to_save_your_changes">Сохранить изменения?</string> <string name="do_you_want_to_archive_all_cards_of_the_list">Вы хотите архивировать все карточки из %1$s?</string> + <string name="do_you_want_to_archive_all_cards_of_the_filtered_list">Переместить в архив все отобранные в списке «%1$s» карточки?</string> <plurals name="do_you_want_to_delete_the_current_list"> <item quantity="one">Это действие безвозвратно удалит %1$d карточку этого списка.</item> <item quantity="few">Это действие безвозвратно удалит %1$d карточки этого списка.</item> @@ -170,11 +169,9 @@ <string name="open_in_browser">Открыть в браузере</string> <string name="updating_card">Обновление карточки…</string> - <!-- Move lists --> <string name="move_list_right">Переместить вправо</string> <string name="move_list_left">Переместить влево</string> - <!-- Filter --> <string name="filter_no_filter">Все</string> <string name="filter_overdue">Просроченные</string> <string name="filter_today">Сегодня</string> @@ -185,7 +182,6 @@ <string name="filter_by_assigned_user">Отфильтровать по назначению</string> <string name="filter_by_duedate">Отфильтровать по сроку исполнения</string> - <!-- Archived cards --> <string name="archived_cards">Карточки в архиве</string> <string name="action_card_dearchive">Отменить архивацию карточки</string> <string name="action_archived_cards">Показать архив карточек</string> @@ -200,11 +196,9 @@ <string name="filter_user_title">Пользователи</string> <string name="filter_duedate_title">Дата исполнения</string> - <!-- Archived boards --> <string name="action_board_dearchive">Отменить архивацию доски</string> <string name="archived_boards">Архив досок</string> - <!-- Errors --> <string name="error">Произошла ошибка</string> <string name="synchronization_failed">Сбой синхронизации</string> <string name="operation_not_yet_supported">Ещё не поддерживается</string> @@ -218,7 +212,8 @@ <string name="error_dialog_title">О нет, что теперь? 🙁</string> <string name="error_dialog_tip_token_mismatch_retry">Попробуйте принудительно закрыть приложение и запустить его снова. Это могло быть связано с некорректным подключением к приложению Nextcloud.</string> - <string name="error_dialog_tip_clear_storage_might_help">Если проблема повторяется, попробуйте для её решения очистить хранилище приложений Nextcloud и Nextcloud Карточки.</string> + <string name="error_dialog_tip_clear_storage_might_help">Если проблема повторяется, попробуйте для её решения очистить хранилища данных приложений Nextcloud и Nextcloud Карточки.</string> + <string name="error_dialog_tip_database_upgrade_failed">Не удалось выполнить обновление базы данных. Сообщите об этой ошибке разработчикам. Чтобы продолжить использовать приложение, требуется выполнить очистку данных приложения.</string> <string name="error_dialog_tip_clear_storage">Для очистки хранилища на откройте приложение «Настройки» и выберите Приложения → Nextcloud / Nextcloud Deck → Хранилище → Очистить хранилище</string> <string name="error_dialog_tip_files_outdated">Ваше приложение Nextcloud устарело. Установите новую версию с Play Store или F-Droid.</string> <string name="error_dialog_tip_files_force_stop">Похоже, что с приложением Nextcloud ведёт себя неожиданным образом. Попробуйте принудительно остановить приложения Nextcloud и Nextcloud Карточки. </string> @@ -232,6 +227,8 @@ <string name="error_dialog_we_need_info">Требуется следующая техническая информация от вас:</string> <string name="error_dialog_redirect">На запрос сервер вернул код состояния HTTP 302, что означает, что приложение Карточки либо не установлено, либо сервер настроен неверно. Такое поведение может являться следствием замены стандартного файла .htaccess администратором сервера или приложением Nextcloud, таким как OID Client.</string> <string name="error_dialog_version_not_parsable">Не удалось определить серверную версию приложения Карточки. Убедитесь, что приложение установлено и включено на сервере.</string> + <string name="error_dialog_account_might_not_be_authorized">Учётная запись из приложения Nextcloud не может использована для авторизации.</string> + <string name="error_dialog_user_not_found_in_database">Данные о текущем пользователе отличаются от сохранённых в базе данных приложения. Это может произойти при использовании каталогов LDAP на сервере Nextcloud.</string> <string name="error_dialog_capabilities_not_parsable">Не удалось получить параметры совместимости сервера. Убедитесь, что сервер работоспособен и у других приложений-клиентов имеется доступ.</string> <string name="error_dialog_attachment_upload_failed">Ошибка передачи вложения на сервер. Используйте другой способ публикации и сообщите разработчикам об этой ошибке.</string> <string name="error_dialog_tip_disable_battery_optimizations">Пожалуйста отключите все оптимизации аккумулятора для приложений Nextcloud и Deck.</string> @@ -252,6 +249,12 @@ <string name="append_text_to_description">Добавить в описание</string> <string name="add_text_as_comment">Добавить как комментарий</string> <string name="progress_count">%1$d из %2$d</string> + <plurals name="progress_error_count"> + <item quantity="one">Во время передачи произошла %1$d ошибка</item> + <item quantity="few">Во время передачи произошло %1$d ошибки</item> + <item quantity="many">Во время передачи произошло %1$d ошибок</item> + <item quantity="other">Во время передачи произошло %1$d ошибки</item> + </plurals> <string name="simple_report">Сообщить</string> <string name="error_action_open_battery_settings">Настройки аккумулятора</string> <string name="move_warning">нет ни одного комментария или вложения, которые можно перенести при перемещении карточки на другую доску</string> @@ -263,6 +266,7 @@ <string name="widget_stack_title">Список</string> <string name="widget_stack_header_icon">иконка заголовка виджета</string> + <string name="widget_stack_placeholder_icon">Подстановочный значок виджета</string> <string name="select_stack">Выберите список</string> <string name="project_type_deck_board">Доска</string> <string name="project_type_deck_card">Карточка</string> @@ -276,5 +280,28 @@ </plurals> <string name="no_assigned_label">Метки не присвоены</string> <string name="single_card">Отдельная карточка</string> + <string name="project_type_room">Комната конференции</string> <string name="simple_move">Переместить</string> - </resources> + <string name="cannot_upload_files_without_permission">Отсутствуют права для загрузки файла</string> + <string name="clone_cards">Скопировать карточку</string> + <string name="simple_clone">Скопировать</string> + <string name="user_avatar">Изображение профиля</string> + <string name="simple_unassign">Отменить назначение</string> + <string name="simple_contact">Контакт</string> + <string name="simple_file">Файл</string> + <string name="simple_camera">Камера</string> + <string name="min_api_21">Эта возможность поддерживается на Android версии 5 и старше</string> + <string name="take_photo">Сделать фотографию</string> + <string name="take_photo_switch_camera">Переключить камеру</string> + <string name="take_photo_toggle_torch">Подсветка</string> + <string name="show_all_contacts">Показать все контакты</string> + <string name="show_all_files">Показать всё файлы</string> + <string name="recent">Недавние</string> + <string name="upload_a_new_attachment">Загрузить вложение</string> + <string name="contacts">Контакты</string> + <string name="downloads">Загрузки</string> + <string name="files">Файлы</string> + <string name="gallery">Галерея</string> + <string name="simple_attach">вложить</string> + <string name="add_stack_widget">Добавить виджет списка</string> +</resources> diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index 62d41c57a..624e48ef6 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Posledný účet</string> <string name="drawer_manage_accounts">Spravovať účty</string> - <!-- Simple values --> <string name="simple_boards">Nástenky</string> <string name="simple_add">Pridať</string> <string name="simple_save">Uložiť</string> @@ -45,7 +44,6 @@ <string name="delete_board">Zmazať nástenku</string> <string name="delete_something">Zmazať %1$s</string> - <!-- About --> <string name="about">O aplikácii</string> <string name="about_version_title">Verzia</string> <string name="about_version">Momentálne používate %1$s</string> @@ -170,11 +168,9 @@ <string name="open_in_browser">Otvoriť v prehliadači</string> <string name="updating_card">Aktualizácia karty…</string> - <!-- Move lists --> <string name="move_list_right">Presunúť zoznam doprava</string> <string name="move_list_left">Presunúť zoznam doľava</string> - <!-- Filter --> <string name="filter_no_filter">Všetko</string> <string name="filter_overdue">Po termíne</string> <string name="filter_today">Dnes</string> @@ -185,7 +181,6 @@ <string name="filter_by_assigned_user">Filtrovať podľa priradeného používateľa</string> <string name="filter_by_duedate">Filtrovať podľa termínu</string> - <!-- Archived cards --> <string name="archived_cards">Archivované karty</string> <string name="action_card_dearchive">Odarchivovať kartu</string> <string name="action_archived_cards">Prechádzať archivované karty</string> @@ -200,11 +195,9 @@ <string name="filter_user_title">Používatelia</string> <string name="filter_duedate_title">Termín dokončenia</string> - <!-- Archived boards --> <string name="action_board_dearchive">Zrušiť archiváciu nástenky</string> <string name="archived_boards">Archivované nástenky</string> - <!-- Errors --> <string name="error">Vyskytla sa chyba</string> <string name="synchronization_failed">Synchronizácia zlyhala</string> <string name="operation_not_yet_supported">Zatiaľ nepodporované</string> diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index b7328a127..77e23ca7c 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Zadnji račun</string> <string name="drawer_manage_accounts">Upravljanje z računi</string> - <!-- Simple values --> <string name="simple_boards">Zbirke</string> <string name="simple_add">Dodaj</string> <string name="simple_save">Shrani</string> @@ -45,7 +44,6 @@ <string name="delete_board">Izbriši zbirko</string> <string name="delete_something">Izbriši %1$s</string> - <!-- About --> <string name="about">O programu</string> <string name="about_version_title">Različica</string> <string name="about_version">Trenutno je v uporabi %1$s</string> @@ -171,11 +169,9 @@ <string name="open_in_browser">Odpri v brskalniku</string> <string name="updating_card">Poteka posodabljanje naloge ...</string> - <!-- Move lists --> <string name="move_list_right">Pomakni seznam desno</string> <string name="move_list_left">Pomakni seznam levo</string> - <!-- Filter --> <string name="filter_no_filter">Vse</string> <string name="filter_overdue">Preteklo</string> <string name="filter_today">Danes</string> @@ -186,7 +182,6 @@ <string name="filter_by_assigned_user">Filtriraj po dodeljenem uporabniku</string> <string name="filter_by_duedate">Filtriraj po datumu preteka</string> - <!-- Archived cards --> <string name="archived_cards">Arhivirane naloge</string> <string name="action_card_dearchive">Razveljavi arhiviranje naloge</string> <string name="action_archived_cards">Prebrskaj med arhiviranimi nalogami</string> @@ -201,11 +196,9 @@ <string name="filter_user_title">Uporabniki</string> <string name="filter_duedate_title">Datum preteka</string> - <!-- Archived boards --> <string name="action_board_dearchive">Razveljavi arhiviranje zbirke</string> <string name="archived_boards">Arhivirane zbirke</string> - <!-- Errors --> <string name="error">Prišlo je do napake</string> <string name="synchronization_failed">Usklajevanje je spodletelo</string> <string name="operation_not_yet_supported">Možnost še ni podprta</string> @@ -301,4 +294,14 @@ <string name="take_photo">Zajemi posnetek</string> <string name="take_photo_switch_camera">Preklopi kamero</string> <string name="take_photo_toggle_torch">Preklopi bliskavico</string> - </resources> + <string name="show_all_contacts">Prikaži vse stike</string> + <string name="show_all_files">Pokaži vse datoteke</string> + <string name="recent">Nedavne</string> + <string name="upload_a_new_attachment">Pošlji novo prilogo</string> + <string name="contacts">Stiki</string> + <string name="downloads">Prejemi</string> + <string name="files">Datoteke</string> + <string name="gallery">Galerija</string> + <string name="simple_attach">pripni</string> + <string name="add_stack_widget">Dodaj gradnik seznama</string> +</resources> diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index ec1cfa296..e87f183df 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Последњи налог</string> <string name="drawer_manage_accounts">Управљање налозима</string> - <!-- Simple values --> <string name="simple_boards">Табле</string> <string name="simple_add">Додај</string> <string name="simple_save">Сачувај</string> @@ -45,7 +44,6 @@ <string name="delete_board">Избриши таблу</string> <string name="delete_something">Обриши %1$s</string> - <!-- About --> <string name="about">О програму</string> <string name="about_version_title">Верзија</string> <string name="about_version">Тренутно користите %1$s</string> @@ -169,11 +167,9 @@ <string name="open_in_browser">Отвори у прегледачу</string> <string name="updating_card">Ажурирам картицу…</string> - <!-- Move lists --> <string name="move_list_right">Помери списак удесно</string> <string name="move_list_left">Помери списак улево</string> - <!-- Filter --> <string name="filter_no_filter">Све</string> <string name="filter_overdue">Прошао рок</string> <string name="filter_today">Данас</string> @@ -184,7 +180,6 @@ <string name="filter_by_assigned_user">Филтрирај по додељеном кориснику</string> <string name="filter_by_duedate">Филтрирај по року</string> - <!-- Archived cards --> <string name="archived_cards">Архивиране картице</string> <string name="action_card_dearchive">Поништи архивирање картице</string> <string name="action_archived_cards">Прегледај архивиране картице</string> @@ -199,11 +194,9 @@ <string name="filter_user_title">Корисници</string> <string name="filter_duedate_title">Рок</string> - <!-- Archived boards --> <string name="action_board_dearchive">Поништи архивирање табле</string> <string name="archived_boards">Архивиране табле</string> - <!-- Errors --> <string name="error">Дошло је до грешке</string> <string name="synchronization_failed">Синхронизација није успела</string> <string name="operation_not_yet_supported">Није још подржано</string> diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 98bd27e93..afc762bff 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Sista konto</string> <string name="drawer_manage_accounts">Hantera konton</string> - <!-- Simple values --> <string name="simple_boards">Tavlor</string> <string name="simple_add">Lägg till</string> <string name="simple_save">Spara</string> @@ -45,7 +44,6 @@ <string name="delete_board">Ta bort tavla</string> <string name="delete_something">Ta bort %1$s</string> - <!-- About --> <string name="about">Om</string> <string name="about_version_title">Version</string> <string name="about_version">Du använder för närvarande %1$s</string> @@ -167,11 +165,9 @@ <string name="open_in_browser">Öppna i webbläsare</string> <string name="updating_card">Uppdaterar kortet...</string> - <!-- Move lists --> <string name="move_list_right">Flytta listan åt höger</string> <string name="move_list_left">Flytta listan åt vänster</string> - <!-- Filter --> <string name="filter_no_filter">Alla</string> <string name="filter_overdue">Förfallen</string> <string name="filter_today">Idag</string> @@ -182,7 +178,6 @@ <string name="filter_by_assigned_user">Filtrera efter tilldelad användare</string> <string name="filter_by_duedate">Filtrera efter förfallodatum</string> - <!-- Archived cards --> <string name="archived_cards">Arkiverade kort</string> <string name="action_card_dearchive">Ångra kortarkivering</string> <string name="action_archived_cards">Bläddra i arkiverade kort</string> @@ -197,11 +192,9 @@ <string name="filter_user_title">Användare</string> <string name="filter_duedate_title">Slutdatum</string> - <!-- Archived boards --> <string name="action_board_dearchive">Ångra tavelarkivering</string> <string name="archived_boards">Arkiverade tavlor</string> - <!-- Errors --> <string name="error">Ett fel inträffade</string> <string name="synchronization_failed">Synkroniseringen misslyckades</string> <string name="operation_not_yet_supported">Stöds inte än</string> diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 60ff93521..c5c09d4fa 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Son hesap</string> <string name="drawer_manage_accounts">Hesap yönetimi</string> - <!-- Simple values --> <string name="simple_boards">Katlar</string> <string name="simple_add">Ekle</string> <string name="simple_save">Kaydet</string> @@ -45,7 +44,6 @@ <string name="delete_board">Panoyu sil</string> <string name="delete_something">%1$s Sil</string> - <!-- About --> <string name="about">Hakkında</string> <string name="about_version_title">Sürüm</string> <string name="about_version">Şu anda %1$s kullanıyorsunuz</string> @@ -167,11 +165,9 @@ <string name="open_in_browser">Tarayıcıda aç</string> <string name="updating_card">Kart güncelleniyor…</string> - <!-- Move lists --> <string name="move_list_right">Listeyi sağa taşı</string> <string name="move_list_left">Listeyi sola taşı</string> - <!-- Filter --> <string name="filter_no_filter">Tümü</string> <string name="filter_overdue">Zamanı geçmiş</string> <string name="filter_today">Bugün</string> @@ -182,7 +178,6 @@ <string name="filter_by_assigned_user">Atanmış kullanıcıya göre süz</string> <string name="filter_by_duedate">Bitiş tarihine göre süz</string> - <!-- Archived cards --> <string name="archived_cards">Arşivlenmiş kartlar</string> <string name="action_card_dearchive">Kart arşivlemeyi geri al</string> <string name="action_archived_cards">Arşivlenmiş kartlara göz at</string> @@ -197,11 +192,9 @@ <string name="filter_user_title">Kullanıcılar</string> <string name="filter_duedate_title">Bitiş tarihi</string> - <!-- Archived boards --> <string name="action_board_dearchive">Pano arşivlemeyi geri al</string> <string name="archived_boards">Arşivlenmiş panolar</string> - <!-- Errors --> <string name="error">Bir sorun çıktı</string> <string name="synchronization_failed">Eşitlenemedi</string> <string name="operation_not_yet_supported">Henüz desteklenmiyor</string> @@ -266,8 +259,8 @@ <string name="card_does_not_yet_exist">Kart henüz panoda bulunmuyor</string> <string name="widget_stack_title">Listele</string> - <string name="widget_stack_header_icon">Araç başlık simgesi</string> - <string name="widget_stack_placeholder_icon">Araç yer belirteci simgesi</string> + <string name="widget_stack_header_icon">Pano bileşeni başlık simgesi</string> + <string name="widget_stack_placeholder_icon">Pano bileşeni yer belirteci simgesi</string> <string name="select_stack">Liste seçin</string> <string name="project_type_deck_board">Tahta panosu</string> <string name="project_type_deck_card">Tahta kartı</string> @@ -302,4 +295,5 @@ <string name="files">Dosyalar</string> <string name="gallery">Galeri</string> <string name="simple_attach">ekle</string> + <string name="add_stack_widget">Liste pano bileşeni ekle</string> </resources> diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index f82c949dc..572da1f8e 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">Останній обліковий запис</string> <string name="drawer_manage_accounts">Облікові записи</string> - <!-- Simple values --> <string name="simple_boards">Дошки</string> <string name="simple_add">Додати</string> <string name="simple_save">Зберегти</string> @@ -45,7 +44,6 @@ <string name="delete_board">Вилучити дошку</string> <string name="delete_something">Вилучити %1$s</string> - <!-- About --> <string name="about">Про програму</string> <string name="about_version_title">Версія</string> <string name="about_version">Ви використовуєте%1$s</string> @@ -169,11 +167,9 @@ <string name="open_in_browser">Відкрити у переглядачі</string> <string name="updating_card">Оновлюю картку...</string> - <!-- Move lists --> <string name="move_list_right">Пересунути список праворуч</string> <string name="move_list_left">Пересунути список ліворуч</string> - <!-- Filter --> <string name="filter_no_filter">Всі</string> <string name="filter_overdue">Протерміновано</string> <string name="filter_today">Сьогодні</string> @@ -184,7 +180,6 @@ <string name="filter_by_assigned_user">Відібрати за призначеним користувачем</string> <string name="filter_by_duedate">Відібрати за датою завершення</string> - <!-- Archived cards --> <string name="archived_cards">Заархівовані картки</string> <string name="action_card_dearchive">Скасувати архівування картки</string> <string name="action_archived_cards">Перегляд заархівованих карток</string> @@ -199,11 +194,9 @@ <string name="filter_user_title">Користувачі</string> <string name="filter_duedate_title">Дата завершення</string> - <!-- Archived boards --> <string name="action_board_dearchive">Скасувати архівування дошки</string> <string name="archived_boards">Архівовані дошки</string> - <!-- Errors --> <string name="error">Сталася помилка </string> <string name="synchronization_failed">Синхронізація не вдалася</string> <string name="operation_not_yet_supported">Ще не підтримується</string> diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 9aea4a1ba..20f7d4b05 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -8,7 +8,6 @@ <string name="drawer_end_account">最后一个账号</string> <string name="drawer_manage_accounts">管理账号</string> - <!-- Simple values --> <string name="simple_boards">面板</string> <string name="simple_add">添加</string> <string name="simple_save">保存</string> @@ -45,7 +44,6 @@ <string name="delete_board">删除面板</string> <string name="delete_something">删除 %1$s</string> - <!-- About --> <string name="about">关于</string> <string name="about_version_title">版本</string> <string name="about_version">您当前正在使用 %1$s</string> @@ -162,11 +160,9 @@ <string name="open_in_browser">在浏览器中打开</string> <string name="updating_card">正在更新卡片…</string> - <!-- Move lists --> <string name="move_list_right">将列表移动到右侧</string> <string name="move_list_left">将列表移动到左侧</string> - <!-- Filter --> <string name="filter_no_filter">全部</string> <string name="filter_overdue">逾期</string> <string name="filter_today">今天</string> @@ -177,7 +173,6 @@ <string name="filter_by_assigned_user">根据指定用户过滤</string> <string name="filter_by_duedate">根据截止日期过滤</string> - <!-- Archived cards --> <string name="archived_cards">已存档卡片</string> <string name="action_card_dearchive">取消存档卡片</string> <string name="action_archived_cards">浏览已存档卡片</string> @@ -194,7 +189,6 @@ <string name="archived_boards">已归档面板</string> - <!-- Errors --> <string name="error">发生了一个错误</string> <string name="synchronization_failed">同步失败</string> <string name="operation_not_yet_supported">尚未支持</string> diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 55812677c..d7907027a 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -12,6 +12,9 @@ <color name="bg_card_wrapper">#fafafa</color> <color name="dark_fg_primary">#e5e5e5</color> + <color name="activity_create">#00D400</color> + <color name="activity_delete">#D40000</color> + <!-- due date colors --> <color name="due_tomorrow">#7fffc53a</color> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e6aa9a02d..b152a2a6f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,7 +10,6 @@ <string name="drawer_end_account">Last account</string> <string name="drawer_manage_accounts">Manage accounts</string> - <!-- Simple values --> <string name="simple_boards">Boards</string> <string name="simple_add">Add</string> <string name="simple_save">Save</string> @@ -47,7 +46,6 @@ <string name="delete_board">Delete board</string> <string name="delete_something">Delete %1$s</string> - <!-- About --> <string name="about">About</string> <string name="about_version_title">Version</string> <string name="about_version">You are currently using %1$s</string> @@ -107,7 +105,6 @@ <string name="label_clear_due_date">Clear due date</string> <string name="label_add">Add %1$s</string> - <!-- URLs --> <string name="url_maintainer" translatable="false">https://www.niedermann.it/</string> <string name="url_about_icon_author" translatable="false">https://github.com/nextcloud/deck/commit/8c04ea8dc99e9b392f4039e8e5e6964d5a6d3453#diff-f3716cc279904617b1a21078526b6bf1R1</string> <string name="url_source" translatable="false">https://github.com/stefan-niedermann/nextcloud-deck</string> @@ -192,11 +189,9 @@ <string name="open_in_browser">Open in browser</string> <string name="updating_card">Updating card…</string> - <!-- Move lists --> <string name="move_list_right">Move list right</string> <string name="move_list_left">Move list left</string> - <!-- Filter --> <string name="filter_no_filter">All</string> <string name="filter_overdue">Overdue</string> <string name="filter_today">Today</string> @@ -207,7 +202,6 @@ <string name="filter_by_assigned_user">Filter by assigned user</string> <string name="filter_by_duedate">Filter by due date</string> - <!-- Archived cards --> <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> @@ -222,11 +216,9 @@ <string name="filter_user_title">Users</string> <string name="filter_duedate_title">Due date</string> - <!-- Archived boards --> <string name="action_board_dearchive">Undo board archiving</string> <string name="archived_boards">Archived boards</string> - <!-- Errors --> <string name="error">An error appeared</string> <string name="synchronization_failed">Synchronization failed</string> <string name="operation_not_yet_supported">Not yet supported</string> @@ -328,6 +320,7 @@ <string name="files">Files</string> <string name="gallery">Gallery</string> <string name="simple_attach">attach</string> + <string name="add_stack_widget">Add list widget</string> <string name="add_filter_widget">Add filter widget</string> <string name="simple_order">Order</string> </resources> diff --git a/app/src/test/java/it/niedermann/nextcloud/deck/ProjectUtilTest.java b/app/src/test/java/it/niedermann/nextcloud/deck/ProjectUtilTest.java index 2c03f5952..1f5f5e602 100644 --- a/app/src/test/java/it/niedermann/nextcloud/deck/ProjectUtilTest.java +++ b/app/src/test/java/it/niedermann/nextcloud/deck/ProjectUtilTest.java @@ -10,7 +10,7 @@ import static org.junit.Assert.assertThrows; public class ProjectUtilTest { @Test public void extractBoardIdAndCardIdFromUrl() { - // Valid board URLs + // Valid board URLs with # and with index.php assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("index.php/apps/deck/#/board/4"), new long[]{4}); assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("/index.php/apps/deck/#/board/4"), new long[]{4}); assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("example.com/index.php/apps/deck/#/board/4"), new long[]{4}); @@ -22,7 +22,43 @@ public class ProjectUtilTest { assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/index.php/apps/deck/#/board/4/card/0"), new long[]{4}); assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/index.php/apps/deck/#/board/4/foo"), new long[]{4}); - // Valid card URLs + // Valid board URLs with # and without index.php + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("apps/deck/#/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("/apps/deck/#/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("example.com/apps/deck/#/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("http://example.com/apps/deck/#/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/apps/deck/#/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/#/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/#/board/4/card"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/#/board/4/card/"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/#/board/4/card/0"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/#/board/4/foo"), new long[]{4}); + + // Valid board URLs without # and with index.php + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("index.php/apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("/index.php/apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("example.com/index.php/apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("http://example.com/index.php/apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/index.php/apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/index.php/apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/index.php/apps/deck/board/4/card"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/index.php/apps/deck/board/4/card/"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/index.php/apps/deck/board/4/card/0"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/index.php/apps/deck/board/4/foo"), new long[]{4}); + + // Valid board URLs without # and without index.php + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("/apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("example.com/apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("http://example.com/apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/board/4"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/board/4/card"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/board/4/card/"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/board/4/card/0"), new long[]{4}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/board/4/foo"), new long[]{4}); + + // Valid card URLs with # and with index.php assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("index.php/apps/deck/#/board/4/card/6"), new long[]{4, 6}); assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("/index.php/apps/deck/#/board/4/card/6"), new long[]{4, 6}); assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("example.com/index.php/apps/deck/#/board/4/card/6"), new long[]{4, 6}); @@ -31,6 +67,33 @@ public class ProjectUtilTest { assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/index.php/apps/deck/#/board/4/card/6/"), new long[]{4, 6}); assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/index.php/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + // Valid card URLs with # and without index.php + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("example.com/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("http://example.com/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/apps/deck/#/board/4/card/6/"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + + // Valid card URLs without # and with index.php + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("index.php/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("/index.php/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("example.com/index.php/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("http://example.com/index.php/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/index.php/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/index.php/apps/deck/#/board/4/card/6/"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/index.php/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + + // Valid card URLs without # and without index.php + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("example.com/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("http://example.com/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/apps/deck/#/board/4/card/6/"), new long[]{4, 6}); + assertArrayEquals(ProjectUtil.extractBoardIdAndCardIdFromUrl("https://example.com/nextcloud/apps/deck/#/board/4/card/6"), new long[]{4, 6}); + // URLs to talk assertThrows(IllegalArgumentException.class, () -> ProjectUtil.extractBoardIdAndCardIdFromUrl("index.php/call/qkzhe5k2")); assertThrows(IllegalArgumentException.class, () -> ProjectUtil.extractBoardIdAndCardIdFromUrl("/index.php/call/qkzhe5k2")); @@ -54,5 +117,8 @@ public class ProjectUtilTest { assertThrows(IllegalArgumentException.class, () -> ProjectUtil.extractBoardIdAndCardIdFromUrl("/index.php/apps/deck/#/board/0")); assertThrows(IllegalArgumentException.class, () -> ProjectUtil.extractBoardIdAndCardIdFromUrl("/index.php/apps/deck/#/board/0/card/3")); assertThrows(IllegalArgumentException.class, () -> ProjectUtil.extractBoardIdAndCardIdFromUrl("/index.php/apps/deck/#/board//card/3")); + assertThrows(IllegalArgumentException.class, () -> ProjectUtil.extractBoardIdAndCardIdFromUrl("/index.php/apps/deck/board/0")); + assertThrows(IllegalArgumentException.class, () -> ProjectUtil.extractBoardIdAndCardIdFromUrl("/index.php/apps/deck/board/0/card/3")); + assertThrows(IllegalArgumentException.class, () -> ProjectUtil.extractBoardIdAndCardIdFromUrl("/index.php/apps/deck/board//card/3")); } } |