From 458c20625ceceedba7dc8d4c3200a981fa2216c2 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 21 Feb 2023 14:32:15 +0600 Subject: [PATCH 1/4] 6684-Automatically_pick_murena_account issue: https://gitlab.e.foundation/e/backlog/-/issues/6684 - We want to pick murena account if it is setup in the device. - Refactor accountSyncUtil code --- app/build.gradle | 2 +- .../importaccount/ImportAccountActivity.java | 34 +++++++++++ .../ImportMurenaAccountViewModel.java | 57 +++++++++++++++++++ .../constant/MurenaAccountConstants.java | 26 +++++++++ .../notes/shared/util/AccountSyncUtil.java | 29 ++++++---- 5 files changed, 135 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java create mode 100644 app/src/main/java/it/niedermann/owncloud/notes/shared/constant/MurenaAccountConstants.java diff --git a/app/build.gradle b/app/build.gradle index ed7d513e8..1c308d3f0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,7 +56,7 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6' // Nextcloud SSO - implementation 'foundation.e.lib:Android-SingleSignOn:1.0.3-alpha' + implementation 'foundation.e.lib:Android-SingleSignOn:1.0.4-alpha' implementation ('com.github.stefan-niedermann:android-commons:0.2.7') { exclude group: 'com.github.nextcloud', module: 'Android-SingleSignOn' } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportAccountActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportAccountActivity.java index 1f5143665..8f8a5ed2e 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportAccountActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportAccountActivity.java @@ -14,7 +14,9 @@ import androidx.preference.PreferenceManager; import com.nextcloud.android.sso.AccountImporter; import com.nextcloud.android.sso.exceptions.AccountImportCancelledException; import com.nextcloud.android.sso.exceptions.AndroidGetAccountsPermissionNotGranted; +import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountPermissionNotGrantedException; import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotInstalledException; +import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotSupportedException; import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException; import com.nextcloud.android.sso.exceptions.UnknownErrorException; import com.nextcloud.android.sso.helper.SingleAccountHelper; @@ -44,6 +46,8 @@ public class ImportAccountActivity extends AppCompatActivity { private final ExecutorService executor = Executors.newSingleThreadExecutor(); private ImportAccountViewModel importAccountViewModel; + private ImportMurenaAccountViewModel importMurenaAccountViewModel; + private ActivityImportAccountBinding binding; @Override @@ -54,6 +58,7 @@ public class ImportAccountActivity extends AppCompatActivity { binding = ActivityImportAccountBinding.inflate(getLayoutInflater()); importAccountViewModel = new ViewModelProvider(this).get(ImportAccountViewModel.class); + importMurenaAccountViewModel = new ViewModelProvider(this).get(ImportMurenaAccountViewModel.class); setContentView(binding.getRoot()); @@ -75,6 +80,8 @@ public class ImportAccountActivity extends AppCompatActivity { AccountImporter.requestAndroidAccountPermissionsAndPickAccount(this); } }); + + handleAutoMurenaAccountSetup(); } @Override @@ -178,4 +185,31 @@ public class ImportAccountActivity extends AppCompatActivity { binding.progressText.setVisibility(View.GONE); }); } + + private void handleAutoMurenaAccountSetup() { + if (importMurenaAccountViewModel.isMurenaAccountPresent()) { + binding.addButton.setEnabled(false); + binding.addButton.setVisibility(View.INVISIBLE); + binding.status.setVisibility(View.GONE); + + pickMurenaAccount(); + } + } + + private void pickMurenaAccount() { + try { + AccountImporter.pickAccount(this, importMurenaAccountViewModel.getMurenaAccount()); + } catch (NextcloudFilesAppNotInstalledException | + NextcloudFilesAppNotSupportedException e) { + UiExceptionManager.showDialogForException(this, e); + Log.w(TAG, "============================================================="); + Log.w(TAG, "Nextcloud app is not installed. Cannot choose account"); + e.printStackTrace(); + } catch (AndroidGetAccountsPermissionNotGranted | + NextcloudFilesAppAccountPermissionNotGrantedException e) { + binding.addButton.setEnabled(true); + binding.addButton.setVisibility(View.VISIBLE); + AccountImporter.requestAndroidAccountPermissionsAndPickAccount(this); + } + } } \ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java b/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java new file mode 100644 index 000000000..9c9e60da7 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java @@ -0,0 +1,57 @@ +/* + * Copyright MURENA SAS 2023 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package it.niedermann.owncloud.notes.importaccount; + +import android.accounts.Account; +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; + +import java.util.List; + +import it.niedermann.owncloud.notes.shared.util.AccountSyncUtil; + +public class ImportMurenaAccountViewModel extends AndroidViewModel { + + private Account account; + + public ImportMurenaAccountViewModel(@NonNull Application application) { + super(application); + retrieveAccount(); + } + + private void retrieveAccount() { + List accounts = AccountSyncUtil.getMuenaAccounts(getApplication()); + + if (accounts.isEmpty()) { + return; + } + + if (AccountSyncUtil.isSyncEnable(accounts.get(0))) { + account = accounts.get(0); // retrieve the first account, as we have policy that one murena account per device + } + } + + public boolean isMurenaAccountPresent() { + return account != null; + } + + public Account getMurenaAccount() { + return account; + } +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/constant/MurenaAccountConstants.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/constant/MurenaAccountConstants.java new file mode 100644 index 000000000..88eae9cfb --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/constant/MurenaAccountConstants.java @@ -0,0 +1,26 @@ +/* + * Copyright MURENA SAS 2023 + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package it.niedermann.owncloud.notes.shared.constant; + +public final class MurenaAccountConstants { + + public static final String MURENA_ACCOUNT_TYPE = "e.foundation.webdav.eelo"; + public static final String NOTES_CONTENT_AUTHORITY = "foundation.e.notes.android.providers.AppContentProvider"; + + private MurenaAccountConstants() { + } +} diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/AccountSyncUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/AccountSyncUtil.java index 45cd09646..76e61e45a 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/AccountSyncUtil.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/AccountSyncUtil.java @@ -19,33 +19,32 @@ package it.niedermann.owncloud.notes.shared.util; import android.accounts.AccountManager; import android.content.ContentResolver; import android.content.Context; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import it.niedermann.owncloud.notes.shared.constant.MurenaAccountConstants; import trikita.log.Log; import it.niedermann.owncloud.notes.persistence.entity.Account; -public class AccountSyncUtil { +public final class AccountSyncUtil { private static final String TAG = AccountSyncUtil.class.getSimpleName(); - private static final String murena_account_type = "e.foundation.webdav.eelo"; - private static final String notes_content_authority = "foundation.e.notes.android.providers.AppContentProvider"; private AccountSyncUtil() { throw new UnsupportedOperationException("Do not instantiate this util class."); } - private static android.accounts.Account[] getMurenaAccountsOnDevice(AccountManager accountManager) { - return accountManager.getAccountsByType(murena_account_type); - } - - private static boolean isSyncEnable(android.accounts.Account account) { - return ContentResolver.getMasterSyncAutomatically() && ContentResolver.getSyncAutomatically(account, notes_content_authority); + public static boolean isSyncEnable(android.accounts.Account account) { + return ContentResolver.getMasterSyncAutomatically() && ContentResolver.getSyncAutomatically(account, MurenaAccountConstants.NOTES_CONTENT_AUTHORITY); } public static boolean isSyncEnable(Context context, Account account) { - AccountManager accountManager = AccountManager.get(context); - try { - android.accounts.Account[] murenaAccounts = getMurenaAccountsOnDevice(accountManager); + List murenaAccounts = getMuenaAccounts(context); for (android.accounts.Account murenaAccount : murenaAccounts) { if (account.getAccountName().equals(murenaAccount.name)) { @@ -59,4 +58,10 @@ public class AccountSyncUtil { return true; } + public static List getMuenaAccounts(Context context) { + AccountManager accountManager = AccountManager.get(context); + return Arrays.stream(accountManager.getAccountsByType(MurenaAccountConstants.MURENA_ACCOUNT_TYPE)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } } -- GitLab From 0b459be7bf72a76a5f6ccd2f348f8573cb01ffa3 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 21 Feb 2023 16:59:20 +0600 Subject: [PATCH 2/4] check murena account loaded or not in mainActivity --- .../importaccount/ImportMurenaAccountViewModel.java | 11 +++++++++++ .../niedermann/owncloud/notes/main/MainActivity.java | 9 +++++++-- .../niedermann/owncloud/notes/main/MainViewModel.java | 4 ++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java b/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java index 9c9e60da7..d3f5dff5d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java @@ -23,6 +23,7 @@ import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; import java.util.List; +import java.util.Objects; import it.niedermann.owncloud.notes.shared.util.AccountSyncUtil; @@ -54,4 +55,14 @@ public class ImportMurenaAccountViewModel extends AndroidViewModel { public Account getMurenaAccount() { return account; } + + public boolean shouldLoadMurenaAccount(List noteAccounts) { + if (!isMurenaAccountPresent()) { + return false; + } + + return noteAccounts.stream() + .filter(Objects::nonNull) + .noneMatch(noteAccount -> noteAccount.getAccountName().equals(account.name)); + } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java index ebdfaa795..4d423ec6d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java @@ -23,6 +23,8 @@ import android.graphics.PorterDuff; import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; + +import it.niedermann.owncloud.notes.importaccount.ImportMurenaAccountViewModel; import trikita.log.Log; import android.view.View; @@ -107,6 +109,8 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A protected final ExecutorService executor = Executors.newCachedThreadPool(); protected MainViewModel mainViewModel; + + private ImportMurenaAccountViewModel importMurenaAccountViewModel; private CategoryViewModel categoryViewModel; private boolean gridView = true; @@ -142,6 +146,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A super.onCreate(savedInstanceState); mainViewModel = new ViewModelProvider(this).get(MainViewModel.class); + importMurenaAccountViewModel = new ViewModelProvider(this).get(ImportMurenaAccountViewModel.class); categoryViewModel = new ViewModelProvider(this).get(CategoryViewModel.class); CapabilitiesWorker.update(this); binding = DrawerLayoutBinding.inflate(getLayoutInflater()); @@ -160,8 +165,8 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A setupNavigationList(); setupNotesList(); - mainViewModel.getAccountsCount().observe(this, (count) -> { - if (count == 0) { + mainViewModel.getAccounts$().observe(this, (accounts) -> { + if (accounts.isEmpty() || importMurenaAccountViewModel.shouldLoadMurenaAccount(accounts)) { startActivityForResult(new Intent(this, ImportAccountActivity.class), ImportAccountActivity.REQUEST_CODE_IMPORT_ACCOUNT); } else { executor.submit(() -> { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/MainViewModel.java b/app/src/main/java/it/niedermann/owncloud/notes/main/MainViewModel.java index 4b721e898..5ce45bd3e 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/MainViewModel.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/MainViewModel.java @@ -603,8 +603,8 @@ public class MainViewModel extends AndroidViewModel { return repo.getLocalModifiedNotes(accountId); } - public LiveData getAccountsCount() { - return repo.countAccounts$(); + public LiveData> getAccounts$() { + return repo.getAccounts$(); } @WorkerThread -- GitLab From f918d70d6aeb3cd31beac17df1695e113cdf314a Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 21 Feb 2023 18:45:20 +0600 Subject: [PATCH 3/4] Fix importAccount page navigation issue --- .../owncloud/notes/importaccount/ImportAccountActivity.java | 5 +++++ .../java/it/niedermann/owncloud/notes/main/MainActivity.java | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportAccountActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportAccountActivity.java index 8f8a5ed2e..1d2e02e77 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportAccountActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportAccountActivity.java @@ -3,6 +3,8 @@ package it.niedermann.owncloud.notes.importaccount; import android.accounts.NetworkErrorException; import android.content.Intent; import android.os.Bundle; + +import it.niedermann.owncloud.notes.main.MainActivity; import trikita.log.Log; import android.view.View; @@ -118,6 +120,9 @@ public class ImportAccountActivity extends AppCompatActivity { Log.i(TAG, capabilities.toString()); BrandingUtil.saveBrandColors(ImportAccountActivity.this, capabilities.getColor(), capabilities.getTextColor()); setResult(RESULT_OK); + Intent intent = new Intent(ImportAccountActivity.this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); finish(); }); SyncWorker.update(ImportAccountActivity.this, PreferenceManager.getDefaultSharedPreferences(ImportAccountActivity.this) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java index 4d423ec6d..c1d4a119d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/MainActivity.java @@ -167,7 +167,10 @@ public class MainActivity extends LockedActivity implements NoteClickListener, A mainViewModel.getAccounts$().observe(this, (accounts) -> { if (accounts.isEmpty() || importMurenaAccountViewModel.shouldLoadMurenaAccount(accounts)) { - startActivityForResult(new Intent(this, ImportAccountActivity.class), ImportAccountActivity.REQUEST_CODE_IMPORT_ACCOUNT); + Intent intent = new Intent(this, ImportAccountActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + finish(); } else { executor.submit(() -> { try { -- GitLab From 17464134993c41b3c2edc91153e6d42fdaf41821 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Wed, 22 Feb 2023 09:03:39 +0600 Subject: [PATCH 4/4] Fix typo & exact veriable according to review --- .../notes/importaccount/ImportMurenaAccountViewModel.java | 8 +++++--- .../notes/shared/constant/MurenaAccountConstants.java | 3 --- .../owncloud/notes/shared/util/AccountSyncUtil.java | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java b/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java index d3f5dff5d..002e794b6 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/importaccount/ImportMurenaAccountViewModel.java @@ -37,14 +37,16 @@ public class ImportMurenaAccountViewModel extends AndroidViewModel { } private void retrieveAccount() { - List accounts = AccountSyncUtil.getMuenaAccounts(getApplication()); + List accounts = AccountSyncUtil.getMurenaAccounts(getApplication()); if (accounts.isEmpty()) { return; } - if (AccountSyncUtil.isSyncEnable(accounts.get(0))) { - account = accounts.get(0); // retrieve the first account, as we have policy that one murena account per device + Account murenaAccount = accounts.get(0); // retrieve the first account, as we have policy that one murena account per device + + if (AccountSyncUtil.isSyncEnable(murenaAccount)) { + account = murenaAccount; } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/constant/MurenaAccountConstants.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/constant/MurenaAccountConstants.java index 88eae9cfb..3bbd3f760 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/constant/MurenaAccountConstants.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/constant/MurenaAccountConstants.java @@ -20,7 +20,4 @@ public final class MurenaAccountConstants { public static final String MURENA_ACCOUNT_TYPE = "e.foundation.webdav.eelo"; public static final String NOTES_CONTENT_AUTHORITY = "foundation.e.notes.android.providers.AppContentProvider"; - - private MurenaAccountConstants() { - } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/AccountSyncUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/AccountSyncUtil.java index 76e61e45a..c3429987b 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/AccountSyncUtil.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/AccountSyncUtil.java @@ -44,7 +44,7 @@ public final class AccountSyncUtil { public static boolean isSyncEnable(Context context, Account account) { try { - List murenaAccounts = getMuenaAccounts(context); + List murenaAccounts = getMurenaAccounts(context); for (android.accounts.Account murenaAccount : murenaAccounts) { if (account.getAccountName().equals(murenaAccount.name)) { @@ -58,7 +58,7 @@ public final class AccountSyncUtil { return true; } - public static List getMuenaAccounts(Context context) { + public static List getMurenaAccounts(Context context) { AccountManager accountManager = AccountManager.get(context); return Arrays.stream(accountManager.getAccountsByType(MurenaAccountConstants.MURENA_ACCOUNT_TYPE)) .filter(Objects::nonNull) -- GitLab