From 14f2cdf29495ddc86d52cac4e18ccc742a7a48f6 Mon Sep 17 00:00:00 2001 From: desperateCoder Date: Mon, 9 Dec 2019 20:56:24 +0100 Subject: #211 Attachments: WIP --- .../it/niedermann/nextcloud/deck/api/DeckAPI.java | 13 ++++-- .../nextcloud/deck/model/Attachment.java | 13 +++++- .../deck/persistence/sync/SyncManager.java | 50 +++++++++++++--------- .../persistence/sync/adapters/ServerAdapter.java | 24 +++++++++++ .../sync/adapters/db/DataBaseAdapter.java | 4 ++ .../sync/adapters/db/dao/AttachmentDao.java | 4 ++ .../helpers/providers/AttachmentDataProvider.java | 41 +++++++----------- .../sync/helpers/providers/CardDataProvider.java | 2 +- 8 files changed, 99 insertions(+), 52 deletions(-) (limited to 'app/src/main') 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 6e7d2c209..525aa2ff9 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 @@ -16,6 +16,7 @@ import it.niedermann.nextcloud.deck.model.full.FullStack; import it.niedermann.nextcloud.deck.model.propagation.CardUpdate; import it.niedermann.nextcloud.deck.model.propagation.Reorder; import okhttp3.MultipartBody; +import okhttp3.ResponseBody; import retrofit2.http.Body; import retrofit2.http.DELETE; import retrofit2.http.Field; @@ -121,15 +122,19 @@ public interface DeckAPI { // ### ATTACHMENTS + @GET("boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}") + Observable 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") - Observable> getAttachments(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Header(MODIFIED_SINCE_HEADER) String lastSync); + Observable> getAttachments(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId); - @POST("boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachment?type=deck_file") @Multipart + @POST("boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachment?type=deck_file") Observable uploadAttachment(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Part MultipartBody.Part type, @Part MultipartBody.Part attachment); - @PUT("boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachments/{attachmentId}") - Observable updateAttachment(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Path("attachmentId") long attachmentId); + @Multipart + @PUT("boards/{boardId}/stacks/{stackId}/cards/{cardId}/attachment?type=deck_file") + Observable 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}") Observable deleteAttachment(@Path("boardId") long boardId, @Path("stackId") long stackId, @Path("cardId") long cardId, @Path("attachmentId") long attachmentId); 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 e1e48a918..5bfaff1c5 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 @@ -1,5 +1,10 @@ package it.niedermann.nextcloud.deck.model; +import android.content.ContentResolver; +import android.content.Context; +import android.net.Uri; +import android.webkit.MimeTypeMap; + import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; @@ -22,7 +27,7 @@ import it.niedermann.nextcloud.deck.model.interfaces.AbstractRemoteEntity; public class Attachment extends AbstractRemoteEntity { private long cardId; - private String type; + private String type = "deck_file"; private String data; private Date createdAt; private String createdBy; @@ -139,6 +144,12 @@ public class Attachment extends AbstractRemoteEntity { this.localPath = localPath; } + public static String getMimetypeForUri(Context context, Uri uri) { + ContentResolver cR = context.getContentResolver(); + MimeTypeMap mime = MimeTypeMap.getSingleton(); + return mime.getExtensionFromMimeType(cR.getType(uri)); + } + @Override public boolean equals(Object o) { if (this == o) return true; 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 26f82682d..f07314685 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 @@ -1,10 +1,8 @@ package it.niedermann.nextcloud.deck.persistence.sync; import android.app.Activity; -import android.content.ContentResolver; import android.content.Context; import android.net.Uri; -import android.webkit.MimeTypeMap; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -44,6 +42,7 @@ import it.niedermann.nextcloud.deck.persistence.sync.helpers.SyncHelper; import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.AbstractSyncDataProvider; import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.AccessControlDataProvider; import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.ActivityDataProvider; +import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.AttachmentDataProvider; import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.BoardDataProvider; import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.CardDataProvider; import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.CardPropagationDataProvider; @@ -892,40 +891,51 @@ public class SyncManager { } } - public void addAttachmentToCard(long accountId, long localCardId, @NonNull Uri uri) { + public LiveData addAttachmentToCard(long accountId, long localCardId, @NonNull Uri uri) { + MutableLiveData liveData = new MutableLiveData<>(); doAsync(() -> { + Attachment attachment = new Attachment(); + attachment.setCardId(localCardId); + attachment.setMimetype(Attachment.getMimetypeForUri(dataBaseAdapter.getContext(), uri)); + attachment.setLocalPath(uri.getPath()); + attachment.setCreatedAt(new Date()); + dataBaseAdapter.createAttachment(accountId, attachment); if (serverAdapter.hasInternetConnection()) { Card card = dataBaseAdapter.getCardByLocalIdDirectly(accountId, localCardId); Stack stack = dataBaseAdapter.getStackByLocalIdDirectly(card.getStackId()); Board board = dataBaseAdapter.getBoardByLocalIdDirectly(stack.getBoardId()); - - ContentResolver cR = dataBaseAdapter.getContext().getContentResolver(); - MimeTypeMap mime = MimeTypeMap.getSingleton(); - String type = mime.getExtensionFromMimeType(cR.getType(uri)); - serverAdapter.uploadAttachment(board.getId(), stack.getId(), card.getId(), type, uri, new IResponseCallback(dataBaseAdapter.readAccountDirectly(accountId)) { - @Override - public void onResponse(Attachment response) { - DeckLog.log("uploading " + uri.getPath() + " successful."); - } - }); + Account account = dataBaseAdapter.getAccountByIdDirectly(card.getAccountId()); + new DataPropagationHelper(serverAdapter, dataBaseAdapter) + .createEntity(new AttachmentDataProvider(null, board, stack, card, Collections.singletonList(attachment)), attachment, new IResponseCallback(account) { + @Override + public void onResponse(Attachment response) { + liveData.postValue(response); + } + }); } }); + return liveData; } - public void deleteAttachmentOfCard(long accountId, long localCardId, long localAttachmentId) { + public LiveData deleteAttachmentOfCard(long accountId, long localCardId, long localAttachmentId) { + MutableLiveData liveData = new MutableLiveData<>(); doAsync(() -> { if (serverAdapter.hasInternetConnection()) { Card card = dataBaseAdapter.getCardByLocalIdDirectly(accountId, localCardId); Stack stack = dataBaseAdapter.getStackByLocalIdDirectly(card.getStackId()); Board board = dataBaseAdapter.getBoardByLocalIdDirectly(stack.getBoardId()); Attachment attachment = dataBaseAdapter.getAttachmentByLocalIdDirectly(accountId, localAttachmentId); - serverAdapter.deleteAttachment(board.getId(), stack.getId(), card.getId(), attachment.getId(), new IResponseCallback(dataBaseAdapter.readAccountDirectly(accountId)) { - @Override - public void onResponse(Void response) { - DeckLog.log("deleted Attachment "+attachment.getBasename()); - } - }); + Account account = dataBaseAdapter.getAccountByIdDirectly(card.getAccountId()); + + new DataPropagationHelper(serverAdapter, dataBaseAdapter) + .deleteEntity(new AttachmentDataProvider(null, board, stack, card, Collections.singletonList(attachment)), attachment, new IResponseCallback(account) { + @Override + public void onResponse(Attachment response) { + liveData.postValue(response); + } + }); } }); + 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 150662988..b59cbcc63 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 @@ -45,6 +45,7 @@ import it.niedermann.nextcloud.deck.util.DateUtil; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.RequestBody; +import okhttp3.ResponseBody; public class ServerAdapter { @@ -276,8 +277,31 @@ public class ServerAdapter { MultipartBody.Part typePart = MultipartBody.Part.createFormData("type", attachment.getName(), RequestBody.create(MediaType.parse("text/plain"), "deck_file")); RequestHelper.request(sourceActivity, provider, () -> provider.getDeckAPI().uploadAttachment(remoteBoardId, remoteStackId, remoteCardId, typePart, filePart), responseCallback); } + + public void getAttachmentsForCard(Long remoteBoardId, long remoteStackId, long remoteCardId, String contentType, Uri attachmentUri, IResponseCallback> responseCallback) { + ensureInternetConnection(); + RequestHelper.request(sourceActivity, provider, () -> provider.getDeckAPI().getAttachments(remoteBoardId, remoteStackId, remoteCardId), responseCallback); + } + + public void updateAttachment(Long remoteBoardId, long remoteStackId, long remoteCardId, long remoteAttachmentId, String contentType, Uri attachmentUri, IResponseCallback responseCallback) { + ensureInternetConnection(); + File attachment = new File(attachmentUri.getPath()); + MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", attachment.getName(), RequestBody.create(MediaType.parse(contentType), attachment)); + MultipartBody.Part typePart = MultipartBody.Part.createFormData("type", attachment.getName(), RequestBody.create(MediaType.parse("text/plain"), "deck_file")); + RequestHelper.request(sourceActivity, provider, () -> provider.getDeckAPI().updateAttachment(remoteBoardId, remoteStackId, remoteCardId, remoteAttachmentId, typePart, filePart), responseCallback); + } + + public void downloadAttachment(Long remoteBoardId, long remoteStackId, long remoteCardId, long remoteAttachmentId, IResponseCallback responseCallback) { + ensureInternetConnection(); + RequestHelper.request(sourceActivity, provider, () -> provider.getDeckAPI().downloadAttachment(remoteBoardId, remoteStackId, remoteCardId, remoteAttachmentId), responseCallback); + } + public void deleteAttachment(Long remoteBoardId, long remoteStackId, long remoteCardId, long remoteAttachmentId, IResponseCallback responseCallback) { ensureInternetConnection(); RequestHelper.request(sourceActivity, provider, () -> provider.getDeckAPI().deleteAttachment(remoteBoardId, remoteStackId, remoteCardId, remoteAttachmentId), responseCallback); } + public void restoreAttachment(Long remoteBoardId, long remoteStackId, long remoteCardId, long remoteAttachmentId, IResponseCallback responseCallback) { + ensureInternetConnection(); + RequestHelper.request(sourceActivity, provider, () -> provider.getDeckAPI().restoreAttachment(remoteBoardId, remoteStackId, remoteCardId, remoteAttachmentId), responseCallback); + } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java index d96a3c0af..684096318 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java @@ -485,6 +485,10 @@ public class DataBaseAdapter { return db.getAttachmentDao().getAttachmentByLocalIdDirectly(accountId, id); } + public List getLocallyChangedAttachmentsByLocalCardIdDirectly(long accountId, Long localCardId) { + return db.getAttachmentDao().getLocallyChangedAttachmentsByLocalCardIdDirectly(accountId, localCardId); + } + public long createAttachment(long accountId, Attachment attachment) { attachment.setAccountId(accountId); return db.getAttachmentDao().insert(attachment); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AttachmentDao.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AttachmentDao.java index 7899ed261..a8c0e5442 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AttachmentDao.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AttachmentDao.java @@ -18,4 +18,8 @@ public interface AttachmentDao extends GenericDao { @Query("SELECT * FROM attachment where accountId = :accountId and localId = :id") Attachment getAttachmentByLocalIdDirectly(long accountId, Long id); + + @Query("SELECT * FROM attachment WHERE accountId = :accountId and cardId = :localCardId and (status<>1 or id is null or lastModified <> lastModifiedLocal)") + List getLocallyChangedAttachmentsByLocalCardIdDirectly(long accountId, long localCardId); + } \ No newline at end of file diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/AttachmentDataProvider.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/AttachmentDataProvider.java index 184185fb6..4a9688b3c 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/AttachmentDataProvider.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/AttachmentDataProvider.java @@ -1,30 +1,30 @@ package it.niedermann.nextcloud.deck.persistence.sync.helpers.providers; -import android.content.ContentResolver; import android.net.Uri; -import android.webkit.MimeTypeMap; import java.io.File; import java.util.Date; import java.util.List; -import it.niedermann.nextcloud.deck.DeckLog; import it.niedermann.nextcloud.deck.api.IResponseCallback; import it.niedermann.nextcloud.deck.model.Attachment; import it.niedermann.nextcloud.deck.model.Board; import it.niedermann.nextcloud.deck.model.Card; import it.niedermann.nextcloud.deck.model.Stack; -import it.niedermann.nextcloud.deck.model.full.FullCard; import it.niedermann.nextcloud.deck.persistence.sync.adapters.ServerAdapter; import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.DataBaseAdapter; public class AttachmentDataProvider extends AbstractSyncDataProvider { - private FullCard card; + private Card card; + private Board board; + private Stack stack; private List attachments; - public AttachmentDataProvider(AbstractSyncDataProvider parent, FullCard card, List attachments) { + public AttachmentDataProvider(AbstractSyncDataProvider parent, Board board, Stack stack, Card card, List attachments) { super(parent); + this.board = board; + this.stack = stack; this.card = card; this.attachments = attachments; } @@ -41,13 +41,13 @@ public class AttachmentDataProvider extends AbstractSyncDataProvider @Override public long createInDB(DataBaseAdapter dataBaseAdapter, long accountId, Attachment attachment) { - attachment.setCardId(card.getCard().getLocalId()); + attachment.setCardId(card.getLocalId()); return dataBaseAdapter.createAttachment(accountId, attachment); } @Override public void updateInDB(DataBaseAdapter dataBaseAdapter, long accountId, Attachment attachment, boolean setStatus) { - attachment.setCardId(card.getCard().getLocalId()); + attachment.setCardId(card.getLocalId()); dataBaseAdapter.updateAttachment(accountId, attachment, setStatus); } @@ -64,37 +64,26 @@ public class AttachmentDataProvider extends AbstractSyncDataProvider @Override public void createOnServer(ServerAdapter serverAdapter, DataBaseAdapter dataBaseAdapter, long accountId, IResponseCallback responder, Attachment entity) { - Card card = dataBaseAdapter.getCardByLocalIdDirectly(accountId, entity.getCardId()); - Stack stack = dataBaseAdapter.getStackByLocalIdDirectly(card.getStackId()); - Board board = dataBaseAdapter.getBoardByLocalIdDirectly(stack.getBoardId()); - - ContentResolver cR = dataBaseAdapter.getContext().getContentResolver(); - MimeTypeMap mime = MimeTypeMap.getSingleton(); Uri uri = Uri.fromFile(new File(entity.getLocalPath())); - String type = mime.getExtensionFromMimeType(cR.getType(uri)); - serverAdapter.uploadAttachment(board.getId(), stack.getId(), card.getId(), type, uri, new IResponseCallback(dataBaseAdapter.readAccountDirectly(accountId)) { - @Override - public void onResponse(Attachment response) { - DeckLog.log("uploading " + uri.getPath() + " successful."); - } - }); + String type = Attachment.getMimetypeForUri(dataBaseAdapter.getContext(), uri); + serverAdapter.uploadAttachment(board.getId(), stack.getId(), card.getId(), type, uri, responder); } @Override public void updateOnServer(ServerAdapter serverAdapter, DataBaseAdapter dataBaseAdapter, long accountId, IResponseCallback callback, Attachment entity) { - //TODO: implement + Uri uri = Uri.fromFile(new File(entity.getLocalPath())); + String type = Attachment.getMimetypeForUri(dataBaseAdapter.getContext(), uri); + serverAdapter.updateAttachment(board.getId(), stack.getId(), card.getId(), entity.getId(), type, uri, callback); + } @Override public void deleteOnServer(ServerAdapter serverAdapter, long accountId, IResponseCallback callback, Attachment entity, DataBaseAdapter dataBaseAdapter) { - Card card = dataBaseAdapter.getCardByLocalIdDirectly(accountId, entity.getCardId()); - Stack stack = dataBaseAdapter.getStackByLocalIdDirectly(card.getStackId()); - Board board = dataBaseAdapter.getBoardByLocalIdDirectly(stack.getBoardId()); serverAdapter.deleteAttachment(board.getId(), stack.getId(), card.getId(), entity.getId(), callback); } @Override public List getAllChangedFromDB(DataBaseAdapter dataBaseAdapter, long accountId, Date lastSync) { - return null; + return dataBaseAdapter.getLocallyChangedAttachmentsByLocalCardIdDirectly(accountId, card.getLocalId()); } } 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 114464e35..a1adbe389 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 @@ -130,7 +130,7 @@ public class CardDataProvider extends AbstractSyncDataProvider { syncHelper.fixRelations(new CardUserRelationshipProvider(existingEntity.getCard(), existingEntity.getAssignedUsers())); if(attachments != null && !attachments.isEmpty()){ - syncHelper.doSyncFor(new AttachmentDataProvider(this, existingEntity, attachments)); + syncHelper.doSyncFor(new AttachmentDataProvider(this, board, stack.getStack(), existingEntity.getCard(), attachments)); } } -- cgit v1.2.3