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

github.com/stefan-niedermann/nextcloud-deck.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Niedermann <info@niedermann.it>2021-03-11 22:24:30 +0300
committerNiedermann IT-Dienstleistungen <stefan-niedermann@users.noreply.github.com>2021-03-12 00:51:04 +0300
commit4e6d0cf9f8d1ea1b1f48cf4aa9582c73bec26c68 (patch)
tree52b0154ffb04f6eb2a6dc245131a05a1eaea7f81
parent2afb1ba66a2001af5c33b12570750172e3139a70 (diff)
Support Deck API 1.1 (server version 1.3+)
Signed-off-by: Stefan Niedermann <info@niedermann.it>
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/api/ApiProvider.java9
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/api/DeckAPI.java110
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/api/NextcloudServerAPI.java19
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/ServerAdapter.java8
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java23
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/attachments/AttachmentViewHolder.java2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/AttachmentViewHolder.java5
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentAdapter.java2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DefaultAttachmentViewHolder.java2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/ImageAttachmentViewHolder.java7
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/util/AttachmentUtil.java44
-rw-r--r--app/src/test/java/it/niedermann/nextcloud/deck/util/AttachmentUtilTest.java18
12 files changed, 170 insertions, 79 deletions
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/api/ApiProvider.java b/app/src/main/java/it/niedermann/nextcloud/deck/api/ApiProvider.java
index e2cfda22e..a6e8da168 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/api/ApiProvider.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/api/ApiProvider.java
@@ -18,19 +18,18 @@ import retrofit2.NextcloudRetrofitApiBuilder;
/**
* Created by david on 26.05.17.
*/
-
public class ApiProvider {
- private static final String DECK_API_ENDPOINT = "/index.php/apps/deck/api/v1.0/";
+ private static final String DECK_API_ENDPOINT = "/index.php/apps/deck/api/";
private static final String NC_API_ENDPOINT = "/ocs/v2.php/";
private DeckAPI deckAPI;
private NextcloudServerAPI nextcloudAPI;
@NonNull
- private Context context;
- private SingleSignOnAccount ssoAccount;
+ private final Context context;
@Nullable
- private String ssoAccountName;
+ private final String ssoAccountName;
+ private SingleSignOnAccount ssoAccount;
public ApiProvider(Context context) {
this(context, null);
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 32e340f0f..0ccfec812 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
@@ -12,6 +12,7 @@ import it.niedermann.nextcloud.deck.model.Board;
import it.niedermann.nextcloud.deck.model.Card;
import it.niedermann.nextcloud.deck.model.Label;
import it.niedermann.nextcloud.deck.model.Stack;
+import it.niedermann.nextcloud.deck.model.enums.EAttachmentType;
import it.niedermann.nextcloud.deck.model.full.FullBoard;
import it.niedermann.nextcloud.deck.model.full.FullCard;
import it.niedermann.nextcloud.deck.model.full.FullStack;
@@ -32,129 +33,146 @@ import retrofit2.http.Part;
import retrofit2.http.Path;
import retrofit2.http.Query;
+/**
+ * @link <a href="https://deck.readthedocs.io/en/latest/API/">Deck REST API</a>
+ */
public interface DeckAPI {
String MODIFIED_SINCE_HEADER = "If-Modified-Since";
String IF_NONE_MATCH = "If-None-Match";
- // ### BOARDS
- @POST("boards")
+
+ // Boards
+
+ @POST("v1.0/boards")
Observable<FullBoard> createBoard(@Body Board board);
- @GET("boards/{id}")
+ @GET("v1.0/boards/{id}")
Observable<FullBoard> getBoard(@Path("id") long id, @Header(MODIFIED_SINCE_HEADER) String lastSync);
- @PUT("boards/{id}")
+ @PUT("v1.0/boards/{id}")
Observable<FullBoard> updateBoard(@Path("id") long id, @Body Board board);
- @DELETE("boards/{id}")
+ @DELETE("v1.0/boards/{id}")
Observable<Void> deleteBoard(@Path("id") long id);
- @DELETE("boards/{id}/undo_delete")
+ @DELETE("v1.0/boards/{id}/undo_delete")
Observable<FullBoard> restoreBoard(@Path("id") long id);
- @GET("boards")
- Observable<ParsedResponse<List<FullBoard>>> getBoards(@Query ("details") boolean verbose, @Header(MODIFIED_SINCE_HEADER) String lastSync, @Header(IF_NONE_MATCH) String eTag);
+ @GET("v1.0/boards")
+ Observable<ParsedResponse<List<FullBoard>>> getBoards(@Query("details") boolean verbose, @Header(MODIFIED_SINCE_HEADER) String lastSync, @Header(IF_NONE_MATCH) String eTag);
+
+ // Stacks
- // ### Stacks
- @POST("boards/{boardId}/stacks")
- Observable<FullStack> createStack(@Path("boardId") long boardId, @Body Stack stack);
+ @POST("v1.0/boards/{boardId}/stacks")
+ Observable<FullStack> createStack(@Path("boardId") long boardId, @Body Stack stack);
- @PUT("boards/{boardId}/stacks/{stackId}")
+ @PUT("v1.0/boards/{boardId}/stacks/{stackId}")
Observable<FullStack> updateStack(@Path("boardId") long boardId, @Path("stackId") long id, @Body Stack stack);
- @DELETE("boards/{boardId}/stacks/{stackId}")
+ @DELETE("v1.0/boards/{boardId}/stacks/{stackId}")
Observable<Void> deleteStack(@Path("boardId") long boardId, @Path("stackId") long id);
- @GET("boards/{boardId}/stacks/{stackId}")
+ @GET("v1.0/boards/{boardId}/stacks/{stackId}")
Observable<FullStack> getStack(@Path("boardId") long boardId, @Path("stackId") long id, @Header(MODIFIED_SINCE_HEADER) String lastSync);
- @GET("boards/{boardId}/stacks")
+ @GET("v1.0/boards/{boardId}/stacks")
Observable<List<FullStack>> getStacks(@Path("boardId") long boardId, @Header(MODIFIED_SINCE_HEADER) String lastSync);
- @GET("boards/{boardId}/stacks/archived")
+ @GET("v1.0/boards/{boardId}/stacks/archived")
Observable<List<Stack>> getArchivedStacks(@Path("boardId") long boardId, @Header(MODIFIED_SINCE_HEADER) String lastSync);
- // ### Cards
- @POST("boards/{boardId}/stacks/{stackId}/cards")
+ // Cards
+
+ @POST("v1.0/boards/{boardId}/stacks/{stackId}/cards")
Observable<FullCard> createCard(@Path("boardId") long boardId, @Path("stackId") long stackId, @Body Card card);
- @PUT("boards/{boardId}/stacks/{stackId}/cards/{cardId}")
+ @PUT("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}")
Observable<FullCard> updateCard(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Body CardUpdate card);
@FormUrlEncoded
- @PUT("boards/{boardId}/stacks/{stackId}/cards/{cardId}/assignLabel")
+ @PUT("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/assignLabel")
Observable<Void> assignLabelToCard(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Field("labelId") long labelId);
@FormUrlEncoded
- @PUT("boards/{boardId}/stacks/{stackId}/cards/{cardId}/removeLabel")
+ @PUT("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/removeLabel")
Observable<Void> unassignLabelFromCard(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Field("labelId") long labelId);
@FormUrlEncoded
- @PUT("boards/{boardId}/stacks/{stackId}/cards/{cardId}/assignUser")
+ @PUT("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/assignUser")
Observable<Void> assignUserToCard(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Field("userId") String userUID);
@FormUrlEncoded
- @PUT("boards/{boardId}/stacks/{stackId}/cards/{cardId}/unassignUser")
- Observable<Void> unassignUserFromCard(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Field("userId") String userUID);
+ @PUT("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/unassignUser")
+ Observable<Void> unassignUserFromCard(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Field("userId") String userUID);
- @PUT("boards/{boardId}/stacks/{stackId}/cards/{cardId}/reorder")
+ @PUT("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/reorder")
Observable<List<FullCard>> moveCard(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Body Reorder reorder);
- @DELETE("boards/{boardId}/stacks/{stackId}/cards/{cardId}")
+ @DELETE("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}")
Observable<Void> deleteCard(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId);
- @GET("boards/{boardId}/stacks/{stackId}/cards/{cardId}")
- Observable<FullCard> getCard(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Header(MODIFIED_SINCE_HEADER) String lastSync);
+ /**
+ * @see <a href="https://github.com/nextcloud/deck/issues/2874">This endpoint does only return {@link Attachment}s of type {@link EAttachmentType.DECK_FILE}</a>
+ */
+ @Deprecated
+ @SuppressWarnings("JavadocReference")
+ @GET("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}")
+ Observable<FullCard> getCard_1_0(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Header(MODIFIED_SINCE_HEADER) String lastSync);
+
+ @GET("v1.1/boards/{boardId}/stacks/{stackId}/cards/{cardId}")
+ Observable<FullCard> getCard_1_1(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Header(MODIFIED_SINCE_HEADER) String lastSync);
- // ### LABELS
- @GET("boards/{boardId}/labels/{labelId}")
+ // Labels
+
+ @GET("v1.0/boards/{boardId}/labels/{labelId}")
Observable<Label> getLabel(@Path("boardId") long boardId, @Path("labelId") long labelId, @Header(MODIFIED_SINCE_HEADER) String lastSync);
- @PUT("boards/{boardId}/labels/{labelId}")
+ @PUT("v1.0/boards/{boardId}/labels/{labelId}")
Observable<Label> updateLabel(@Path("boardId") long boardId, @Path("labelId") long labelId, @Body Label label);
- @POST("boards/{boardId}/labels")
+ @POST("v1.0/boards/{boardId}/labels")
Observable<Label> createLabel(@Path("boardId") long boardId, @Body Label label);
- @DELETE("boards/{boardId}/labels/{labelId}")
+ @DELETE("v1.0/boards/{boardId}/labels/{labelId}")
Observable<Void> deleteLabel(@Path("boardId") long boardId, @Path("labelId") long labelId);
- // ### ATTACHMENTS
- @GET("boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}")
+ // Attachments
+
+ @GET("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}")
Observable<ResponseBody> downloadAttachment(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Path("attachmentId") long attachmentId);
- @GET("boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments")
+ @GET("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments")
Observable<List<Attachment>> getAttachments(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId);
@Multipart
- @POST("boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments")
+ @POST("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments")
Observable<Attachment> uploadAttachment(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Part MultipartBody.Part type, @Part MultipartBody.Part attachment);
@Multipart
- @PUT("boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments")
+ @PUT("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments")
Observable<Attachment> updateAttachment(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Path("attachmentId") long attachmentId, @Part MultipartBody.Part type, @Part MultipartBody.Part attachment);
- @DELETE("boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}")
+ @DELETE("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}")
Observable<Void> deleteAttachment(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Path("attachmentId") long attachmentId);
- @PUT("boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}/restore")
+ @PUT("v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}/restore")
Observable<Attachment> restoreAttachment(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Path("attachmentId") long attachmentId);
- // ### ACL
- @POST("boards/{boardId}/acl")
+
+ // Access control lists
+
+ @POST("v1.0/boards/{boardId}/acl")
Observable<AccessControl> createAccessControl(@Path("boardId") long boardId, @Body AccessControl acl);
- @PUT("boards/{boardId}/acl/{aclId}")
+ @PUT("v1.0/boards/{boardId}/acl/{aclId}")
Observable<AccessControl> updateAccessControl(@Path("boardId") long boardId, @Path("aclId") long aclId, @Body AccessControl acl);
- @DELETE("boards/{boardId}/acl/{aclId}")
+ @DELETE("v1.0/boards/{boardId}/acl/{aclId}")
Observable<Void> deleteAccessControl(@Path("boardId") long boardId, @Path("aclId") long aclId, @Body AccessControl acl);
- // ### COMMENTS
-
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/api/NextcloudServerAPI.java b/app/src/main/java/it/niedermann/nextcloud/deck/api/NextcloudServerAPI.java
index 7b93ace49..54e573d73 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/api/NextcloudServerAPI.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/api/NextcloudServerAPI.java
@@ -24,14 +24,27 @@ import retrofit2.http.PUT;
import retrofit2.http.Path;
import retrofit2.http.Query;
+
+/**
+ * @link <a href="https://deck.readthedocs.io/en/latest/API-Nextcloud/">Nextcloud REST API</a>
+ */
public interface NextcloudServerAPI {
+
+ // Capabilities
+
@GET("cloud/capabilities?format=json")
Observable<ParsedResponse<Capabilities>> getCapabilities(@Header("If-None-Match") String eTag);
+
+ // Projects
+
@GET("collaboration/resources/deck-card/{cardId}?format=json")
Observable<OcsProjectList> getProjectsForCard(@Path("cardId") long cardId);
+
+ // Users
+
@GET("apps/files_sharing/api/v1/sharees?format=json&perPage=20&itemType=0%2C1%2C7")
Observable<OcsUserList> searchUser(@Query("search") String searchTerm);
@@ -41,9 +54,15 @@ public interface NextcloudServerAPI {
@GET("cloud/users/{search}?format=json")
Observable<OcsUser> getSingleUserData(@Path("search") String userUid);
+
+ // Activities
+
@GET("apps/activity/api/v2/activity/filter?format=json&object_type=deck_card&limit=50&since=-1&sort=asc")
Observable<List<Activity>> getActivitiesForCard(@Query("object_id") long cardId);
+
+ // Comments
+
@Headers({
"Accept: application/json",
"Content-Type: application/json;charset=utf-8"
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 f96ff1da0..a1051b98c 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
@@ -222,7 +222,13 @@ public class ServerAdapter {
public void getCard(long boardId, long stackId, long cardId, IResponseCallback<FullCard> responseCallback) {
ensureInternetConnection();
- RequestHelper.request(provider, () -> provider.getDeckAPI().getCard(boardId, stackId, cardId, getLastSyncDateFormatted(responseCallback.getAccount().getId())), responseCallback);
+ RequestHelper.request(provider, () -> {
+ final Account account = responseCallback.getAccount();
+ if(account != null && account.getServerDeckVersionAsObject().supportsFileAttachments()) {
+ return provider.getDeckAPI().getCard_1_1(boardId, stackId, cardId, getLastSyncDateFormatted(responseCallback.getAccount().getId()));
+ }
+ return provider.getDeckAPI().getCard_1_0(boardId, stackId, cardId, getLastSyncDateFormatted(responseCallback.getAccount().getId()));
+ }, responseCallback);
}
public void createCard(long boardId, long stackId, Card card, IResponseCallback<FullCard> 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 ee2aff1a4..6871c8fa6 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
@@ -125,7 +125,7 @@ import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.dao.widgets.fil
FilterWidgetSort.class,
},
exportSchema = false,
- version = 28
+ version = 29
)
@TypeConverters({DateTypeConverter.class, EnumConverter.class})
public abstract class DeckDatabase extends RoomDatabase {
@@ -421,10 +421,13 @@ public abstract class DeckDatabase extends RoomDatabase {
database.execSQL("ALTER TABLE `OcsProjectResource` ADD `etag` TEXT");
}
};
+
+ /**
+ * Reset ETags (comments weren't loading due to bug)
+ */
private static final Migration MIGRATION_24_25 = new Migration(24, 25) {
@Override
public void migrate(SupportSQLiteDatabase database) {
- // Reset etags (comments weren't loading due to bug)
database.execSQL("UPDATE `Account` SET `boardsEtag` = NULL");
database.execSQL("UPDATE `Board` SET `etag` = NULL");
database.execSQL("UPDATE `Stack` SET `etag` = NULL");
@@ -506,6 +509,7 @@ public abstract class DeckDatabase extends RoomDatabase {
database.execSQL("DROP TABLE `StackWidgetModel`");
}
};
+
private static final Migration MIGRATION_27_28 = new Migration(27, 28) {
@Override
public void migrate(SupportSQLiteDatabase database) {
@@ -513,6 +517,20 @@ public abstract class DeckDatabase extends RoomDatabase {
}
};
+ /**
+ * Reset ETags for cards because <a href="https://github.com/nextcloud/deck/issues/2874">the attachments for this card might not be complete</a>.
+ */
+ private static final Migration MIGRATION_28_29 = new Migration(28, 29) {
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("UPDATE `Account` SET `boardsEtag` = NULL");
+ database.execSQL("UPDATE `Board` SET `etag` = NULL");
+ database.execSQL("UPDATE `Stack` SET `etag` = NULL");
+ database.execSQL("UPDATE `Card` SET `etag` = NULL");
+ }
+ };
+
+
public static final RoomDatabase.Callback ON_CREATE_CALLBACK = new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
@@ -593,6 +611,7 @@ public abstract class DeckDatabase extends RoomDatabase {
.addMigrations(MIGRATION_25_26)
.addMigrations(MIGRATION_26_27)
.addMigrations(MIGRATION_27_28)
+ .addMigrations(MIGRATION_28_29)
.fallbackToDestructiveMigration()
.addCallback(ON_CREATE_CALLBACK)
.build();
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 26cd21a3c..336e085d7 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
@@ -39,7 +39,7 @@ public class AttachmentViewHolder extends RecyclerView.ViewHolder {
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());
+ final String uri = AttachmentUtil.getThumbnailUrl(account, cardRemoteId, attachment, binding.preview.getWidth(), binding.preview.getHeight());
Glide.with(parentContext)
.load(uri)
.listener(new RequestListener<Drawable>() {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/AttachmentViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/AttachmentViewHolder.java
index 533bbe322..655ee3986 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/AttachmentViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/AttachmentViewHolder.java
@@ -26,7 +26,10 @@ public abstract class AttachmentViewHolder extends RecyclerView.ViewHolder {
}
public void bind(@NonNull Account account, @NonNull MenuInflater menuInflater, @NonNull FragmentManager fragmentManager, Long cardRemoteId, Attachment attachment, @Nullable View.OnClickListener onClickListener, @ColorInt int mainColor) {
- bind(menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, mainColor, AttachmentUtil.getRemoteOrLocalUrl(account.getUrl(), cardRemoteId, attachment));
+ final String downloadUrl = (attachment.getId() == null || cardRemoteId == null)
+ ? attachment.getLocalPath()
+ : AttachmentUtil.getCopyDownloadUrl(account, cardRemoteId, attachment);
+ bind(menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, mainColor, downloadUrl);
}
@CallSuper
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentAdapter.java
index 74ea070a9..16af8bb8f 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentAdapter.java
@@ -114,7 +114,7 @@ public class CardAttachmentAdapter extends RecyclerView.Adapter<AttachmentViewHo
}
case VIEW_TYPE_DEFAULT:
default: {
- onClickListener = (event) -> openAttachmentInBrowser(context, account.getUrl(), cardRemoteId, attachment.getId());
+ onClickListener = (event) -> openAttachmentInBrowser(account, context, cardRemoteId, attachment);
break;
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DefaultAttachmentViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DefaultAttachmentViewHolder.java
index 2b5358eb9..b41a4e9d1 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DefaultAttachmentViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DefaultAttachmentViewHolder.java
@@ -40,7 +40,7 @@ public class DefaultAttachmentViewHolder 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) {
super.bind(account, menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, mainColor);
getPreview().setImageResource(getIconForMimeType(attachment.getMimetype()));
- itemView.setOnClickListener((event) -> openAttachmentInBrowser(itemView.getContext(), account.getUrl(), cardRemoteId, attachment.getId()));
+ itemView.setOnClickListener((event) -> openAttachmentInBrowser(account, itemView.getContext(), cardRemoteId, attachment));
binding.filename.setText(attachment.getBasename());
binding.filesize.setText(Formatter.formatFileSize(binding.filesize.getContext(), attachment.getFilesize()));
if (attachment.getLastModifiedLocal() != null) {
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 3c95da1b7..b93b3d025 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
@@ -37,10 +37,13 @@ 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) {
- super.bind(menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, mainColor, AttachmentUtil.getRemoteOrLocalUrl(account.getUrl(), cardRemoteId, attachment));
+ final String downloadUrl = (attachment.getId() == null || cardRemoteId == null)
+ ? attachment.getLocalPath()
+ : AttachmentUtil.getCopyDownloadUrl(account, cardRemoteId, attachment);
+ super.bind(menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, mainColor, downloadUrl);
getPreview().post(() -> {
- @Nullable final String uri = AttachmentUtil.getThumbnailUrl(account.getServerDeckVersionAsObject(), account.getUrl(), cardRemoteId, attachment, getPreview().getWidth());
+ @Nullable final String uri = AttachmentUtil.getThumbnailUrl(account, cardRemoteId, attachment, getPreview().getWidth());
Glide.with(getPreview().getContext())
.load(uri)
.placeholder(R.drawable.ic_image_grey600_24dp)
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 aefd14b30..72151832e 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
@@ -21,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.Account;
import it.niedermann.nextcloud.deck.model.Attachment;
import it.niedermann.nextcloud.deck.model.enums.EAttachmentType;
import it.niedermann.nextcloud.deck.model.ocs.Version;
@@ -39,43 +40,62 @@ public class AttachmentUtil {
* 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() &&
+ public static String getThumbnailUrl(@NonNull Account account, @NonNull Long cardRemoteId, @NonNull Attachment attachment, @Px int previewSize) {
+ return getThumbnailUrl(account, cardRemoteId, attachment, previewSize, previewSize);
+ }
+
+ public static String getThumbnailUrl(@NonNull Account account, @NonNull Long cardRemoteId, @NonNull Attachment attachment, @Px int previewWidth, @Px int previewHeight) {
+ return account.getServerDeckVersionAsObject().supportsFileAttachments() &&
EAttachmentType.FILE.equals(attachment.getType()) &&
attachment.getFileId() != null
- ? accountUrl + "/index.php/core/preview?fileId=" + attachment.getFileId() + "&x=" + previewSize + "&y=" + previewSize
- : getRemoteOrLocalUrl(accountUrl, cardRemoteId, attachment);
+ ? account.getUrl() + "/index.php/core/preview?fileId=" + attachment.getFileId() + "&x=" + previewWidth + "&y=" + previewHeight + "&a=true"
+ : getRemoteOrLocalUrl(account.getUrl(), cardRemoteId, attachment);
}
/**
- * @return {@link AttachmentUtil#getRemoteUrl} or {@link Attachment#getLocalPath()} as fallback
+ * @return {@link AttachmentUtil#getDeck_1_0_RemoteUrl} 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) {
+ private static String getRemoteOrLocalUrl(@NonNull String accountUrl, @Nullable Long cardRemoteId, @NonNull Attachment attachment) {
return (attachment.getId() == null || cardRemoteId == null)
? attachment.getLocalPath()
- : getRemoteUrl(accountUrl, cardRemoteId, attachment.getId());
+ : getDeck_1_0_RemoteUrl(accountUrl, cardRemoteId, attachment.getId());
}
/**
* Tries to open the given {@link Attachment} in web browser. Displays a toast on failure.
*/
- public static void openAttachmentInBrowser(@NonNull Context context, @NonNull String accountUrl, Long cardRemoteId, Long attachmentRemoteId) {
+ public static void openAttachmentInBrowser(@NonNull Account account, @NonNull Context context, Long cardRemoteId, Attachment attachment) {
if (cardRemoteId == null) {
Toast.makeText(context, R.string.card_does_not_yet_exist, Toast.LENGTH_LONG).show();
DeckLog.logError(new IllegalArgumentException("cardRemoteId must not be null."));
return;
}
- if (attachmentRemoteId == null) {
+
+ try {
+ context.startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse(getCopyDownloadUrl(account, cardRemoteId, attachment))));
+ } catch (IllegalArgumentException e) {
Toast.makeText(context, R.string.attachment_does_not_yet_exist, Toast.LENGTH_LONG).show();
DeckLog.logError(new IllegalArgumentException("attachmentRemoteId must not be null."));
- return;
}
- context.startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse(AttachmentUtil.getRemoteUrl(accountUrl, cardRemoteId, attachmentRemoteId))));
}
- private static String getRemoteUrl(@NonNull String accountUrl, @NonNull Long cardRemoteId, @NonNull Long attachmentRemoteId) {
+ public static String getCopyDownloadUrl(@NonNull Account account, @NonNull Long cardRemoteId, @NonNull Attachment attachment) {
+ if (attachment.getId() == null) {
+ throw new IllegalArgumentException("attachment id must not be null");
+ }
+
+ return (attachment.getFileId() != null)
+ ? account.getUrl() + "/f/" + attachment.getFileId()
+ : getDeck_1_0_RemoteUrl(account.getUrl(), cardRemoteId, attachment.getId());
+ }
+
+ /**
+ * Attention! This does only work for attachments of type "deck_file" which are a legacy of Deck API 1.0
+ */
+ @Deprecated
+ private static String getDeck_1_0_RemoteUrl(@NonNull String accountUrl, @NonNull Long cardRemoteId, @NonNull Long attachmentRemoteId) {
return accountUrl + "/index.php/apps/deck/cards/" + cardRemoteId + "/attachment/" + attachmentRemoteId;
}
diff --git a/app/src/test/java/it/niedermann/nextcloud/deck/util/AttachmentUtilTest.java b/app/src/test/java/it/niedermann/nextcloud/deck/util/AttachmentUtilTest.java
index 653657540..d2d79adb2 100644
--- a/app/src/test/java/it/niedermann/nextcloud/deck/util/AttachmentUtilTest.java
+++ b/app/src/test/java/it/niedermann/nextcloud/deck/util/AttachmentUtilTest.java
@@ -7,9 +7,9 @@ import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
+import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.Attachment;
import it.niedermann.nextcloud.deck.model.enums.EAttachmentType;
-import it.niedermann.nextcloud.deck.model.ocs.Version;
import static org.junit.Assert.assertEquals;
@@ -19,27 +19,31 @@ 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";
+ final Account accountThatDoesSupportFileAttachments = new Account();
+ final Account accountThatDoesNotSupportFileAttachments = new Account();
+ accountThatDoesSupportFileAttachments.setUrl(accountUrl);
+ accountThatDoesSupportFileAttachments.setServerDeckVersion("1.3.0");
+ accountThatDoesNotSupportFileAttachments.setUrl(accountUrl);
+ accountThatDoesNotSupportFileAttachments.setServerDeckVersion("1.2.0");
final Attachment attachment1 = new Attachment();
attachment1.setFileId(1337L);
attachment1.setType(EAttachmentType.FILE);
- final String thumbnailUrl1 = AttachmentUtil.getThumbnailUrl(versionThatDoesSupportFileAttachments, accountUrl, -1L, attachment1, 500);
+ final String thumbnailUrl1 = AttachmentUtil.getThumbnailUrl(accountThatDoesSupportFileAttachments, -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(815L);
attachment2.setType(EAttachmentType.FILE);
- final String thumbnailUrl2 = AttachmentUtil.getThumbnailUrl(versionThatDoesSupportFileAttachments, accountUrl, 0L, attachment2, 4711);
+ final String thumbnailUrl2 = AttachmentUtil.getThumbnailUrl(accountThatDoesSupportFileAttachments, 0L, attachment2, 4711);
assertEquals("https://example.com/index.php/core/preview?fileId=815&x=4711&y=4711", thumbnailUrl2);
// Given there is an invalid fileId...
final Attachment attachment3 = new Attachment();
attachment3.setId(999L);
attachment3.setFileId(null);
- final String thumbnailUrl3 = AttachmentUtil.getThumbnailUrl(versionThatDoesSupportFileAttachments, accountUrl, 15L, attachment3, 205);
+ final String thumbnailUrl3 = AttachmentUtil.getThumbnailUrl(accountThatDoesSupportFileAttachments, 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);
@@ -47,7 +51,7 @@ public class AttachmentUtilTest {
final Attachment attachment4 = new Attachment();
attachment4.setId(111L);
attachment4.setFileId(222L);
- final String thumbnailUrl4 = AttachmentUtil.getThumbnailUrl(versionThatDoesNotSupportFileAttachments, accountUrl, 333L, attachment4, 444);
+ final String thumbnailUrl4 = AttachmentUtil.getThumbnailUrl(accountThatDoesNotSupportFileAttachments,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);
}