diff options
author | desperateCoder <echotodevnull@gmail.com> | 2020-06-28 18:53:32 +0300 |
---|---|---|
committer | desperateCoder <echotodevnull@gmail.com> | 2020-06-28 18:53:32 +0300 |
commit | a51df7357ec8cd561922acac1a75adb5ef95d3c8 (patch) | |
tree | 8b1f4b7137eb8038ed0bd3fadf11c038432cd770 | |
parent | f2b02909373b67a4a4dbb78b8d4a1f5e56e2125e (diff) |
#453 moveCard ready for first attempt
4 files changed, 119 insertions, 17 deletions
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 b797536dd..52bde0413 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 @@ -1066,6 +1066,7 @@ public class SyncManager { /** * Moves the given {@param originCardLocalId} to the new target coordinates specified by {@param targetAccountId}, {@param targetBoardLocalId} and {@param targetStackLocalId}. * If the {@param targetBoardLocalId} changes, this will apply some logic to make sure that we migrate as much data as possible without the risk of getting an illegal state. + * Attachments are not copied or anything. * <p> * 1) {@link FullCard#labels} * <p> @@ -1086,34 +1087,122 @@ public class SyncManager { @AnyThread public WrappedLiveData<Void> moveCard(long originAccountId, long originCardLocalId, long targetAccountId, long targetBoardLocalId, long targetStackLocalId) { return LiveDataHelper.wrapInLiveData(() -> { + FullCard originalCard = dataBaseAdapter.getFullCardByLocalIdDirectly(originAccountId, originCardLocalId); int newIndex = dataBaseAdapter.getHighestCardOrderInStack(targetStackLocalId) + 1; - Board originalBoard = dataBaseAdapter.getBoardByLocalCardIdDirectly(originCardLocalId); + FullBoard originalBoard = dataBaseAdapter.getFullBoardByLocalCardIdDirectly(originCardLocalId); + // ### maybe shortcut possible? (just moved to another stack) if (targetBoardLocalId == originalBoard.getLocalId()) { reorder(originAccountId, originalCard, targetStackLocalId, newIndex); return null; } + // ### get rid of original card where it is now. Card originalInnerCard = originalCard.getCard(); deleteCard(originalInnerCard); - // clone card itself - originalInnerCard.setAccountId(targetAccountId); - originalInnerCard.setId(null); - originalInnerCard.setLocalId(null); - originalInnerCard.setStatusEnum(DBStatus.LOCAL_EDITED); - originalInnerCard.setStackId(targetStackLocalId); - originalInnerCard.setOrder(newIndex); - long newCardId = dataBaseAdapter.createCard(targetAccountId, originalInnerCard); - originalInnerCard.setLocalId(newCardId); - - FullBoard targetBoard = dataBaseAdapter.getFullBoardByLocalCardIdDirectly(newCardId); + // ### clone card itself + Card targetCard = originalInnerCard; + targetCard.setAccountId(targetAccountId); + targetCard.setId(null); + targetCard.setLocalId(null); + targetCard.setStatusEnum(DBStatus.LOCAL_EDITED); + targetCard.setStackId(targetStackLocalId); + targetCard.setOrder(newIndex); + //TODO: this needs to propagate to server as well, since anything else propagates as well (otherwise card isn't known on server) + FullCard fullCardForServerPropagation = new FullCard(); + fullCardForServerPropagation.setCard(targetCard); - // TODO: clone labels, assign them + Account targetAccount = dataBaseAdapter.getAccountByIdDirectly(targetAccountId); + FullBoard targetBoard = dataBaseAdapter.getFullBoardByLocalIdDirectly(targetAccountId, targetBoardLocalId); + FullStack targetFullStack = dataBaseAdapter.getFullStackByLocalIdDirectly(targetStackLocalId); + User userOfTargetAccount = dataBaseAdapter.getUserByUidDirectly(targetAccountId, targetAccount.getUserName()); + CountDownLatch latch = new CountDownLatch(1); + new DataPropagationHelper(serverAdapter, dataBaseAdapter).createEntity(new CardPropagationDataProvider(null, targetBoard.getBoard(), targetFullStack), fullCardForServerPropagation, new IResponseCallback<FullCard>(targetAccount) { + @Override + public void onResponse(FullCard response) { + targetCard.setId(response.getId()); + targetCard.setLocalId(response.getLocalId()); + latch.countDown(); + } - //TODO: Clone assigned users + @Override + public void onError(Throwable throwable) { + super.onError(throwable); + throw new RuntimeException("unable to create card in moveCard target", throwable); + } + }, (FullCard entity, FullCard response) -> { + response.getCard().setUserId(entity.getCard().getUserId()); + response.getCard().setStackId(targetFullStack.getLocalId()); + }); + try { + latch.await(); + } catch (InterruptedException e) { + DeckLog.logError(e); + throw new RuntimeException("error fulfilling countDownLatch", e); + } + long newCardId = targetCard.getLocalId(); + + // ### clone labels, assign them + // prepare + // has user of targetaccount manage permissions? + boolean hasManagePermission = targetBoard.getBoard().getOwnerId() == userOfTargetAccount.getLocalId(); + List<AccessControl> aclOfTargetBoard = dataBaseAdapter.getAccessControlByLocalBoardIdDirectly(targetAccountId, targetBoard.getLocalId()); + if (!hasManagePermission){ + for (AccessControl accessControl : aclOfTargetBoard) { + if (accessControl.getUserId() == userOfTargetAccount.getLocalId() && accessControl.isPermissionManage()){ + hasManagePermission = true; + break; + } + } + } + // actual doing + for (Label originalLabel : originalCard.getLabels()) { + // already exists? + Label existingMatch = null; + for (Label targetBoardLabel : targetBoard.getLabels()) { + if (originalLabel.getTitle().trim().equalsIgnoreCase(targetBoardLabel.getTitle().trim())){ + existingMatch = targetBoardLabel; + break; + } + } + if (existingMatch == null) { + if (hasManagePermission) { + originalLabel.setBoardId(targetBoardLocalId); + originalLabel.setId(null); + originalLabel.setLocalId(null); + originalLabel.setStatusEnum(DBStatus.LOCAL_EDITED); + originalLabel.setAccountId(targetBoard.getAccountId()); + createAndAssignLabelToCard(originalBoard.getAccountId(), originalLabel, newCardId); + } + } else { + assignLabelToCard(existingMatch, targetCard); + } + } + // ### Clone assigned users + Account originalAccount = dataBaseAdapter.getAccountByIdDirectly(originAccountId); + // same instance? otherwise doesn't make sense + if (originalAccount.getUrl().equalsIgnoreCase(targetAccount.getUrl())){ + for (User assignedUser : originalCard.getAssignedUsers()) { + // has assignedUser at least view permissions? + boolean hasViewPermission = targetBoard.getBoard().getOwnerId() == assignedUser.getLocalId(); + if (!hasViewPermission){ + for (AccessControl accessControl : aclOfTargetBoard) { + if (accessControl.getUserId() == userOfTargetAccount.getLocalId()){ + // ACL exists, so viewing is granted + hasViewPermission = true; + break; + } + } + } + if (hasViewPermission) { + assignUserToCard(assignedUser, targetCard); + } + } + } + // since this is LiveData<Void> return null; }); } 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 962699565..90b1b1c35 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 @@ -522,8 +522,12 @@ public class DataBaseAdapter { return db.getAccessControlDao().getAccessControlByRemoteIdDirectly(accountId, id); } - public LiveData<List<AccessControl>> getAccessControlByLocalBoardId(long accountId, Long id) { - return LiveDataHelper.interceptLiveData(db.getAccessControlDao().getAccessControlByLocalBoardId(accountId, id), this::readRelationsForACL); + public LiveData<List<AccessControl>> getAccessControlByLocalBoardId(long accountId, Long localBoardId) { + return LiveDataHelper.interceptLiveData(db.getAccessControlDao().getAccessControlByLocalBoardId(accountId, localBoardId), this::readRelationsForACL); + } + + public List<AccessControl> getAccessControlByLocalBoardIdDirectly(long accountId, Long localBoardId) { + return db.getAccessControlDao().getAccessControlByLocalBoardIdDirectly(accountId, localBoardId); } public void updateAccessControl(AccessControl entity, boolean setStatus) { diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccessControlDao.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccessControlDao.java index 9dc9b7b3d..2ed1e7d59 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccessControlDao.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccessControlDao.java @@ -17,6 +17,9 @@ public interface AccessControlDao extends GenericDao<AccessControl> { @Query("SELECT * FROM AccessControl WHERE accountId = :accountId and boardId = :localBoardId and status <> 3") LiveData<List<AccessControl>> getAccessControlByLocalBoardId(final long accountId, final long localBoardId); + @Query("SELECT * FROM AccessControl WHERE accountId = :accountId and boardId = :localBoardId and status <> 3") + List<AccessControl> getAccessControlByLocalBoardIdDirectly(final long accountId, final long localBoardId); + @Query("SELECT * FROM AccessControl WHERE accountId = :accountId and id = :remoteId") AccessControl getAccessControlByRemoteIdDirectly(final long accountId, final long remoteId); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java index 650c903b3..10a18bb09 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java @@ -85,7 +85,13 @@ public class LiveDataHelper { public static <T> WrappedLiveData<T> wrapInLiveData(final LiveDataWrapper<T> liveDataWrapper) { final WrappedLiveData<T> liveData = new WrappedLiveData<>(); - doAsync(() -> liveDataWrapper.postResult(liveData)); + doAsync(() -> { + try { + liveDataWrapper.postResult(liveData); + } catch (Throwable t) { + liveData.postError(t); + } + }); return liveData; } |