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-11-25 16:02:21 +0300
committerNiedermann IT-Dienstleistungen <stefan-niedermann@users.noreply.github.com>2021-11-29 17:28:10 +0300
commitbe54e018c49a3899acc2baf182ac6dea4382dbf5 (patch)
treef57a2a51a110481fef1d9ac3023d8cdd2dd0af94 /app/src/main
parente23e826945923ab893dce1330c5e2f71cbb6e062 (diff)
#1165 Refactor PushNotifications
Signed-off-by: Stefan Niedermann <info@niedermann.it>
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java11
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/BoardDao.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationActivity.java85
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationViewModel.java152
5 files changed, 158 insertions, 98 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 7ce19fc16..ef170719f 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
@@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -130,9 +131,9 @@ public class SyncManager {
this.syncHelperFactory = syncHelperFactory;
}
- @AnyThread
- public Board getBoardByAccountAndCardRemoteIdDirectly(long accountId, long cardRemoteId) {
- return dataBaseAdapter.getBoardByAccountAndCardRemoteIdDirectly(accountId, cardRemoteId);
+ @WorkerThread
+ public Optional<Long> getBoardLocalIdByAccountAndCardRemoteIdDirectly(long accountId, long cardRemoteId) {
+ return Optional.ofNullable(dataBaseAdapter.getBoardLocalIdByAccountAndCardRemoteIdDirectly(accountId, cardRemoteId));
}
@WorkerThread
@@ -1590,8 +1591,8 @@ public class SyncManager {
}
@WorkerThread
- public Card getCardByRemoteIDDirectly(long accountId, long remoteId) {
- return dataBaseAdapter.getCardByRemoteIDDirectly(accountId, remoteId);
+ public Optional<Card> getCardByRemoteIDDirectly(long accountId, long remoteId) {
+ return Optional.ofNullable(dataBaseAdapter.getCardByRemoteIDDirectly(accountId, remoteId));
}
public long createUser(long accountId, User user) {
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 cb31ff0b1..790d3a1d5 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
@@ -1113,8 +1113,8 @@ public class DataBaseAdapter {
}
@WorkerThread
- public Board getBoardByAccountAndCardRemoteIdDirectly(long accountId, long cardRemoteId) {
- return db.getBoardDao().getBoardByAccountAndCardRemoteIdDirectly(accountId, cardRemoteId);
+ public Long getBoardLocalIdByAccountAndCardRemoteIdDirectly(long accountId, long cardRemoteId) {
+ return db.getBoardDao().getBoardLocalIdByAccountAndCardRemoteIdDirectly(accountId, cardRemoteId);
}
@WorkerThread
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/BoardDao.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/BoardDao.java
index 89846ac39..4fa7bf8f7 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/BoardDao.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/BoardDao.java
@@ -75,12 +75,12 @@ public interface BoardDao extends GenericDao<Board> {
"WHERE c.id = :cardRemoteId and c.accountId = :accountId")
LiveData<Long> getLocalBoardIdByCardRemoteIdAndAccountId(long cardRemoteId, long accountId);
- @Query("SELECT b.* " +
+ @Query("SELECT b.localId " +
"FROM card c " +
"inner join stack s on s.localId = c.stackId " +
"inner join board b on s.boardId = b.localId " +
"WHERE c.id = :cardRemoteId and c.accountId = :accountId")
- Board getBoardByAccountAndCardRemoteIdDirectly(long accountId, long cardRemoteId);
+ Long getBoardLocalIdByAccountAndCardRemoteIdDirectly(long accountId, long cardRemoteId);
@Query("SELECT count(*) FROM board WHERE accountId = :accountId and archived = 1 and (deletedAt = 0 or deletedAt is null) and status <> 3")
LiveData<Integer> countArchivedBoards(long accountId);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationActivity.java
index 25a255aa1..b824ed305 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationActivity.java
@@ -1,5 +1,9 @@
package it.niedermann.nextcloud.deck.ui;
+import static it.niedermann.nextcloud.deck.ui.PushNotificationViewModel.KEY_MESSAGE;
+import static it.niedermann.nextcloud.deck.ui.PushNotificationViewModel.KEY_SUBJECT;
+
+import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
@@ -7,7 +11,6 @@ import android.view.View;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
-import androidx.annotation.UiThread;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
@@ -17,13 +20,11 @@ import java.util.concurrent.Executors;
import it.niedermann.android.util.ColorUtil;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
-import it.niedermann.nextcloud.deck.api.IResponseCallback;
import it.niedermann.nextcloud.deck.databinding.ActivityPushNotificationBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.ui.card.EditActivity;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionHandler;
-import kotlin.Triple;
/**
* Warning: Do not move this class to another package or folder!
@@ -35,13 +36,6 @@ public class PushNotificationActivity extends AppCompatActivity {
private PushNotificationViewModel viewModel;
private final ExecutorService executor = Executors.newSingleThreadExecutor();
- // Provided by Files app NotificationJob
- private static final String KEY_SUBJECT = "subject";
- private static final String KEY_MESSAGE = "message";
- private static final String KEY_LINK = "link";
- private static final String KEY_ACCOUNT = "account";
- // Optional
- private static final String KEY_CARD_REMOTE_ID = "objectId";
@Override
protected void onResume() {
@@ -70,59 +64,48 @@ public class PushNotificationActivity extends AppCompatActivity {
binding.cancel.setOnClickListener((v) -> finish());
viewModel.getAccount().observe(this, this::applyBrandToSubmitButton);
- executor.submit(() -> viewModel.getCardInformation(
- intent.getStringExtra(KEY_ACCOUNT),
- intent.getStringExtra(KEY_CARD_REMOTE_ID),
- new IResponseCallback<>() {
- @Override
- public void onResponse(Triple<Account, Long, Long> response) {
- runOnUiThread(() -> openCardOnSubmit(response.getFirst(), response.getSecond(), response.getThird()));
- }
-
- @Override
- public void onError(Throwable throwable) {
- IResponseCallback.super.onError(throwable);
- runOnUiThread(() -> fallbackToBrowser(intent.getStringExtra(KEY_LINK)));
- final String params = "Error while receiving push notification:\n"
- + KEY_SUBJECT + ": [" + intent.getStringExtra(KEY_SUBJECT) + "]\n"
- + KEY_MESSAGE + ": [" + intent.getStringExtra(KEY_MESSAGE) + "]\n"
- + KEY_LINK + ": [" + intent.getStringExtra(KEY_LINK) + "]\n"
- + KEY_CARD_REMOTE_ID + ": [" + intent.getStringExtra(KEY_CARD_REMOTE_ID) + "]\n"
- + KEY_ACCOUNT + ": [" + intent.getStringExtra(KEY_ACCOUNT) + "]";
- ExceptionDialogFragment.newInstance(new Exception(params, throwable), null).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
- }
- }));
+ executor.submit(() -> viewModel.getCardInformation(intent.getExtras(), new PushNotificationViewModel.PushNotificationCallback() {
+ @Override
+ public void onResponse(@NonNull PushNotificationViewModel.CardInformation cardInformation) {
+ runOnUiThread(() -> openCardOnSubmit(cardInformation.account, cardInformation.localBoardId, cardInformation.localCardId));
+ }
+
+ @Override
+ public void fallbackToBrowser(@NonNull Uri uri) {
+ runOnUiThread(() -> PushNotificationActivity.this.fallbackToBrowser(uri));
+ }
+
+ @Override
+ @SuppressLint("MissingSuperCall")
+ public void onError(Throwable throwable) {
+ runOnUiThread(() -> displayError(throwable));
+ }
+ }));
}
private void openCardOnSubmit(@NonNull Account account, long boardLocalId, long cardLocalId) {
- binding.submit.setOnClickListener((v) -> launchEditActivity(account, boardLocalId, cardLocalId));
+ binding.submit.setOnClickListener((v) -> {
+ DeckLog.info("Starting", EditActivity.class.getSimpleName(), "with [" + account + ", " + boardLocalId + ", " + cardLocalId + "]");
+ startActivity(EditActivity.createEditCardIntent(this, account, boardLocalId, cardLocalId));
+ finish();
+ });
binding.submit.setText(R.string.simple_open);
applyBrandToSubmitButton(account.getColor());
binding.submit.setEnabled(true);
binding.progress.setVisibility(View.INVISIBLE);
}
- /**
- * If anything goes wrong and we cannot open the card directly, we fall back to open the given link in the webbrowser
- */
- private void fallbackToBrowser(String link) {
+ private void fallbackToBrowser(@NonNull Uri uri) {
DeckLog.warn("Falling back to browser as notification handler.");
- try {
- final var uri = Uri.parse(link);
- binding.submit.setOnClickListener((v) -> startActivity(new Intent(Intent.ACTION_VIEW, uri)));
- binding.submit.setText(R.string.open_in_browser);
- binding.submit.setEnabled(true);
- binding.progress.setVisibility(View.INVISIBLE);
- } catch (Throwable t) {
- DeckLog.logError(t);
- }
+ binding.submit.setOnClickListener((v) -> startActivity(new Intent(Intent.ACTION_VIEW, uri)));
+ binding.submit.setText(R.string.open_in_browser);
+ binding.submit.setEnabled(true);
+ binding.progress.setVisibility(View.INVISIBLE);
}
- @UiThread
- private void launchEditActivity(@NonNull Account account, Long boardId, Long cardId) {
- DeckLog.info("starting", EditActivity.class.getSimpleName(), "with [" + account + ", " + boardId + ", " + cardId + "]");
- startActivity(EditActivity.createEditCardIntent(this, account, boardId, cardId));
- finish();
+ private void displayError(Throwable throwable) {
+ ExceptionDialogFragment.newInstance(throwable, null)
+ .show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
}
@Override
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationViewModel.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationViewModel.java
index 42ef05d0c..612759b9b 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationViewModel.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationViewModel.java
@@ -5,6 +5,8 @@ import static androidx.lifecycle.Transformations.map;
import android.annotation.SuppressLint;
import android.app.Application;
+import android.net.Uri;
+import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -15,15 +17,24 @@ import androidx.lifecycle.MutableLiveData;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.api.IResponseCallback;
import it.niedermann.nextcloud.deck.api.ResponseCallback;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
-import kotlin.Triple;
public class PushNotificationViewModel extends AndroidViewModel {
+ // Provided by Files app NotificationJob
+ static final String KEY_SUBJECT = "subject";
+ static final String KEY_MESSAGE = "message";
+ static final String KEY_LINK = "link";
+ private static final String KEY_ACCOUNT = "account";
+ private static final String KEY_CARD_REMOTE_ID = "objectId";
+
private final SyncManager readAccountSyncManager;
private final MutableLiveData<Account> account = new MutableLiveData<>();
@@ -33,80 +44,145 @@ public class PushNotificationViewModel extends AndroidViewModel {
}
@WorkerThread
- public void getCardInformation(
- @Nullable String accountString,
- @Nullable String cardRemoteIdString,
- @NonNull IResponseCallback<Triple<Account, Long, Long>> callback) {
- if (cardRemoteIdString == null) {
- callback.onError(new NumberFormatException("cardRemoteIdString is null"));
+ public void getCardInformation(@Nullable Bundle bundle, @NonNull PushNotificationCallback callback) {
+ if (bundle == null) {
+ callback.onError(new NullPointerException("Bundle is null"));
return;
}
+
+ final var uri = getUriFromBundle(bundle);
try {
- final long cardRemoteId;
- try {
- DeckLog.verbose("cardRemoteIdString = ", cardRemoteIdString);
- cardRemoteId = Long.parseLong(cardRemoteIdString);
- } catch (NumberFormatException e) {
- callback.onError(e);
- return;
- }
- final var account = readAccountSyncManager.readAccountDirectly(accountString);
- if (account == null) {
- callback.onError(new RuntimeException("Given account for" + accountString + "is null."));
- return;
- }
+ final long cardRemoteId = getCardRemoteId(bundle);
+ final var account = getAccount(bundle);
SingleAccountHelper.setCurrentAccount(getApplication(), account.getName());
final var syncManager = new SyncManager(getApplication());
- DeckLog.verbose("account:", account);
- final var board = syncManager.getBoardByAccountAndCardRemoteIdDirectly(account.getId(), cardRemoteId);
- DeckLog.verbose("BoardLocalId:", board);
- if (board == null) {
- callback.onError(new RuntimeException("Given localBoardId for cardRemoteId" + cardRemoteId + "is null."));
- return;
- }
+ final long boardLocalId = syncManager.getBoardLocalIdByAccountAndCardRemoteIdDirectly(account.getId(), cardRemoteId)
+ .orElseThrow(() -> new NoSuchElementException("Given localBoardId for cardRemoteId" + cardRemoteId + "is null."));
+ DeckLog.verbose("boardLocalId:", boardLocalId);
final var card = syncManager.getCardByRemoteIDDirectly(account.getId(), cardRemoteId);
DeckLog.verbose("Card:", card);
- if (card != null) {
+ if (card.isPresent()) {
syncManager.synchronizeCard(new ResponseCallback<>(account) {
@Override
public void onResponse(Boolean response) {
- callback.onResponse(new Triple<>(account, board.getLocalId(), card.getLocalId()));
+ callback.onResponse(new CardInformation(account, boardLocalId, card.get().getLocalId()));
}
@Override
public void onError(Throwable throwable) {
super.onError(throwable);
- callback.onResponse(new Triple<>(account, board.getLocalId(), card.getLocalId()));
+ callback.onResponse(new CardInformation(account, boardLocalId, card.get().getLocalId()));
}
- }, card);
+ }, card.get());
} else {
- DeckLog.info("Card is not yet available locally. Synchronize board with localId", board);
+ DeckLog.info("Card is not yet available locally. Synchronize board with localId", boardLocalId);
- syncManager.synchronizeBoard(board.getLocalId(), new ResponseCallback<>(account) {
+ syncManager.synchronizeBoard(boardLocalId, new ResponseCallback<>(account) {
@Override
public void onResponse(Boolean response) {
final var card = syncManager.getCardByRemoteIDDirectly(account.getId(), cardRemoteId);
DeckLog.verbose("Card:", card);
- if (card != null) {
- callback.onResponse(new Triple<>(account, board.getLocalId(), card.getLocalId()));
+ if (card.isPresent()) {
+ callback.onResponse(new CardInformation(account, boardLocalId, card.get().getLocalId()));
} else {
- callback.onError(new RuntimeException("Something went wrong while synchronizing the card" + cardRemoteId + " (cardRemoteId). Given fullCard is null."));
+ if(uri.isPresent()) {
+ callback.fallbackToBrowser(uri.get());
+ } else {
+ callback.onError(generateException("Something went wrong while synchronizing the card" + cardRemoteId + " (cardRemoteId). Given fullCard is null.", bundle));
+ }
}
}
@SuppressLint("MissingSuperCall")
@Override
public void onError(Throwable throwable) {
- callback.onError(new RuntimeException("Something went wrong while synchronizing the board with localId" + board));
+ if(uri.isPresent()) {
+ callback.fallbackToBrowser(uri.get());
+ } else {
+ callback.onError(generateException("Something went wrong while synchronizing the board with localId" + boardLocalId, bundle));
+ }
}
});
}
} catch (Throwable t) {
- callback.onError(t);
+ if(uri.isPresent()) {
+ callback.fallbackToBrowser(uri.get());
+ } else {
+ callback.onError(generateException("", bundle, t));
+ }
+ }
+ }
+
+ private long getCardRemoteId(@NonNull Bundle bundle) throws IllegalArgumentException {
+ final String cardRemoteIdString = bundle.getString(KEY_CARD_REMOTE_ID);
+ if (cardRemoteIdString == null) {
+ throw new IllegalArgumentException("cardRemoteIdString is null");
+ }
+ DeckLog.verbose("cardRemoteIdString = ", cardRemoteIdString);
+ return Long.parseLong(cardRemoteIdString);
+ }
+
+ private long getCardRemoteIdFromLink(@NonNull Bundle bundle) {
+ // TODO parse with ProjectUtils
+ return -1L;
+ }
+
+ private Account getAccount(@NonNull Bundle bundle) throws NoSuchElementException {
+ final var accountString = bundle.getString(KEY_ACCOUNT);
+ final var account = readAccountSyncManager.readAccountDirectly(accountString);
+ if (account == null) {
+ throw new NoSuchElementException("Given account for" + accountString + "is null.");
+ }
+ DeckLog.verbose("account:", account);
+ return account;
+ }
+
+ private Optional<Uri> getUriFromBundle(@NonNull Bundle bundle) {
+ try {
+ return Optional.of(Uri.parse(bundle.getString(KEY_LINK)));
+ } catch (Throwable t) {
+ return Optional.empty();
+ }
+ }
+
+ private Exception generateException(@NonNull String message, @Nullable Bundle bundle) {
+ return generateException(message, bundle, null);
+ }
+
+ private Exception generateException(@NonNull String message, @Nullable Bundle bundle, @Nullable Throwable cause) {
+ if (bundle == null) {
+ return new Exception("Bundle is null");
}
+ final var info = "Error while receiving push notification:\n"
+ + message + "\n"
+ + KEY_SUBJECT + ": [" + bundle.getString(KEY_SUBJECT) + "]\n"
+ + KEY_MESSAGE + ": [" + bundle.getString(KEY_MESSAGE) + "]\n"
+ + KEY_LINK + ": [" + bundle.getString(KEY_LINK) + "]\n"
+ + KEY_CARD_REMOTE_ID + ": [" + bundle.getString(KEY_CARD_REMOTE_ID) + "]\n"
+ + KEY_ACCOUNT + ": [" + bundle.getString(KEY_ACCOUNT) + "]";
+ return cause == null
+ ? new Exception(info)
+ : new Exception(info, cause);
}
public LiveData<Integer> getAccount() {
return distinctUntilChanged(map(this.account, Account::getColor));
}
+
+ public interface PushNotificationCallback extends IResponseCallback<CardInformation> {
+ void fallbackToBrowser(@NonNull Uri uri);
+ }
+
+ public static class CardInformation {
+ @NonNull
+ public final Account account;
+ public final long localBoardId;
+ public final long localCardId;
+
+ public CardInformation(@NonNull Account account, long localBoardId, long localCardId) {
+ this.account = account;
+ this.localBoardId = localBoardId;
+ this.localCardId = localCardId;
+ }
+ }
}