diff --git a/app/build.gradle b/app/build.gradle index 615e4a095823fe760660d3052810953874e86566..2d110a622434b979351028099f9dc00980018ee2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,12 +56,19 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6' // Nextcloud SSO - implementation 'com.github.nextcloud:Android-SingleSignOn:0.6.1' - implementation 'com.github.stefan-niedermann:android-commons:0.2.7' - implementation 'com.github.stefan-niedermann.nextcloud-commons:sso-glide:1.6.4' - implementation 'com.github.stefan-niedermann.nextcloud-commons:exception:1.6.4' + implementation 'foundation.e.lib:Android-SingleSignOn:1.0.2-alpha' + implementation ('com.github.stefan-niedermann:android-commons:0.2.7') { + exclude group: 'com.github.nextcloud', module: 'Android-SingleSignOn' + } + implementation ('com.github.stefan-niedermann.nextcloud-commons:sso-glide:1.6.4') { + exclude group: 'com.github.nextcloud', module: 'Android-SingleSignOn' + } + implementation ('com.github.stefan-niedermann.nextcloud-commons:exception:1.6.4') { + exclude group: 'com.github.nextcloud', module: 'Android-SingleSignOn' + } implementation('com.github.stefan-niedermann.nextcloud-commons:markdown:1.6.4') { exclude group: 'org.jetbrains', module: 'annotations-java5' + exclude group: 'com.github.nextcloud', module: 'Android-SingleSignOn' } // Glide diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 490b5b2f040bf0a58be3395ffacbf0c1efa0809f..2d72a0ee0c95d5604348e2dbfabc2bda8de8e038 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -181,5 +181,14 @@ android:name=".providers.AppContentProvider" android:enabled="true" android:exported="true"/> + + + + + + + diff --git a/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionActivity.java index cb51d736bdef3ff12f91ea06d8a618b9a562f481..c06f9e4848601502d4031cf067ca2b9ce9d861e6 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionActivity.java @@ -38,7 +38,7 @@ public class ExceptionActivity extends AppCompatActivity { } final var adapter = new TipsAdapter(this::startActivity); - final String debugInfos = ExceptionUtil.INSTANCE.getDebugInfos(this, throwable, "PROD"); + final String debugInfos = ExceptionUtil.INSTANCE.getDebugInfos(this, throwable, "ACCOUNT_MANAGER"); binding.tips.setAdapter(adapter); binding.tips.setNestedScrollingEnabled(false); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionDialogFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionDialogFragment.java index 33a65173b2074d163c102f2668ef048f1daa5c2a..a0c1a0f0612d99843eef21c93c901d924b877cd0 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionDialogFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/exception/ExceptionDialogFragment.java @@ -57,7 +57,7 @@ public class ExceptionDialogFragment extends AppCompatDialogFragment { final var adapter = new TipsAdapter((actionIntent) -> requireActivity().startActivity(actionIntent)); - final String debugInfos = ExceptionUtil.INSTANCE.getDebugInfos(requireContext(), throwables, "PROD"); + final String debugInfos = ExceptionUtil.INSTANCE.getDebugInfos(requireContext(), throwables, "ACCOUNT_MANAGER"); binding.tips.setAdapter(adapter); binding.stacktrace.setText(debugInfos); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/main/menu/MenuAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/main/menu/MenuAdapter.java index 8112f7ec35d025c1ef25a9ccbd2aae917e2574c2..0f757e8727bc2cb32af4235fe1e08b84a445be18 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/main/menu/MenuAdapter.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/main/menu/MenuAdapter.java @@ -13,6 +13,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.nextcloud.android.sso.Constants; import com.nextcloud.android.sso.helper.VersionCheckHelper; +import com.nextcloud.android.sso.model.FilesAppType; import it.niedermann.owncloud.notes.FormattingHelpActivity; import it.niedermann.owncloud.notes.R; @@ -66,26 +67,12 @@ public class MenuAdapter extends RecyclerView.Adapter { @NonNull private static Intent generateTrashbinIntent(@NonNull Context context, @NonNull Account account) { - // https://github.com/nextcloud/android/pull/8405#issuecomment-852966877 - final int minVersionCode = 30170090; - try { - if (VersionCheckHelper.getNextcloudFilesVersionCode(context, true) > minVersionCode) { - return generateTrashbinAppIntent(context, account, true); - } else if (VersionCheckHelper.getNextcloudFilesVersionCode(context, false) > minVersionCode) { - return generateTrashbinAppIntent(context, account, false); - } else { - // Files app is too old to be able to switch the account when launching the TrashbinActivity - return generateTrashbinWebIntent(account); - } - } catch (PackageManager.NameNotFoundException | SecurityException e) { - e.printStackTrace(); - return generateTrashbinWebIntent(account); - } + return generateTrashbinWebIntent(account); } private static Intent generateTrashbinAppIntent(@NonNull Context context, @NonNull Account account, boolean prod) throws PackageManager.NameNotFoundException { final var packageManager = context.getPackageManager(); - final String packageName = prod ? Constants.PACKAGE_NAME_PROD : Constants.PACKAGE_NAME_DEV; + final String packageName = prod ? FilesAppType.ACCOUNT_MANAGER.packageId : FilesAppType.DEV.packageId; final var intent = new Intent(); intent.setClassName(packageName, "com.owncloud.android.ui.trashbin.TrashbinActivity"); if (packageManager.resolveActivity(intent, 0) != null) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/receiver/AccountRemoveReceiver.java b/app/src/main/java/it/niedermann/owncloud/notes/receiver/AccountRemoveReceiver.java new file mode 100644 index 0000000000000000000000000000000000000000..362a407ed9fd7e09d8fa0a06a6b6ae25d075059f --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/receiver/AccountRemoveReceiver.java @@ -0,0 +1,131 @@ +/* + * 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.receiver; + +import android.accounts.AccountManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.nextcloud.android.sso.helper.SingleAccountHelper; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import it.niedermann.owncloud.notes.persistence.NotesRepository; +import it.niedermann.owncloud.notes.persistence.entity.Account; + +public class AccountRemoveReceiver extends BroadcastReceiver { + + private static final String TAG = AccountRemoveReceiver.class.getSimpleName(); + private static final String[] SUPPORTED_ACCOUNT_TYPES = {"e.foundation.webdav.eelo"}; + private static final String ACTION_ACCOUNT_REMOVE = "android.accounts.action.ACCOUNT_REMOVED"; + + private final ExecutorService executor = Executors.newCachedThreadPool(); + + @Override + public void onReceive(Context context, Intent intent) { + if (!ACTION_ACCOUNT_REMOVE.equals(intent.getAction())) { + return; + } + + var accountName = getAccountName(intent); + + if (accountName == null) { + return; + } + + var repository = NotesRepository.getInstance(context.getApplicationContext()); + deleteAccount(context, repository, accountName); + } + + @Nullable + private String getAccountName(Intent intent) { + if (!isSupportedAccountType(intent)) { + return null; + } + + var accountName = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME); + + if (accountName == null || accountName.trim().isEmpty()) { + return null; + } + + return accountName; + + } + + private boolean isSupportedAccountType(Intent intent) { + var accountTpe = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE); + return Arrays.asList(SUPPORTED_ACCOUNT_TYPES) + .contains(accountTpe); + } + + private void deleteAccount(@NonNull Context context, @NonNull NotesRepository repository, @NonNull String accountName) { + executor.submit(() -> { + final var accounts = repository.getAccounts(); + + for (int i = 0; i < accounts.size(); i++) { + if (accounts.get(i).getAccountName().equals(accountName)) { + updateCurrentAccount(context, accounts, accountName, i); + repository.deleteAccount(accounts.get(i)); + break; + } + } + }); + } + + private void updateCurrentAccount(@NonNull Context context, @NonNull List accounts, @NonNull String toBeDeleteAccountName, int currentIndex) { + if (!isCurrentAccount(context, toBeDeleteAccountName)) { + return; + } + + if (currentIndex > 0) { + selectAccount(context, accounts.get(currentIndex - 1)); + } else if (accounts.size() > 1) { + selectAccount(context, accounts.get(currentIndex + 1)); + } else { + selectAccount(context, null); + } + } + + private boolean isCurrentAccount(@NonNull Context context, @NonNull String accountName) { + try { + var selectedAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context); + + if (selectedAccount == null) { + return false; + } + + return accountName.equals(selectedAccount.name); + } catch (Exception e) { + Log.e(TAG, "Currently selected account not found:", e); + } + + return false; + } + + private void selectAccount(@NonNull Context context, @Nullable Account account) { + SingleAccountHelper.setCurrentAccount(context, (account == null) ? null : account.getAccountName()); + } +} \ No newline at end of file