diff --git a/app/src/main/java/com/nextcloud/client/account/CurrentAccountProvider.java b/app/src/main/java/com/nextcloud/client/account/CurrentAccountProvider.java index 58b3371efcf6..fbe2e8503ccc 100644 --- a/app/src/main/java/com/nextcloud/client/account/CurrentAccountProvider.java +++ b/app/src/main/java/com/nextcloud/client/account/CurrentAccountProvider.java @@ -24,7 +24,7 @@ public interface CurrentAccountProvider { * @return Currently selected {@link Account} or first valid {@link Account} registered in OS or null, if not available at all. */ @Deprecated - @Nullable + @NonNull Account getCurrentAccount(); /** diff --git a/app/src/main/java/com/nextcloud/client/account/UserAccountManagerImpl.java b/app/src/main/java/com/nextcloud/client/account/UserAccountManagerImpl.java index 40709c984c75..1554e68e8113 100644 --- a/app/src/main/java/com/nextcloud/client/account/UserAccountManagerImpl.java +++ b/app/src/main/java/com/nextcloud/client/account/UserAccountManagerImpl.java @@ -18,9 +18,9 @@ import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.text.TextUtils; -import android.util.Log; import com.nextcloud.common.NextcloudClient; +import com.nextcloud.utils.extensions.AccountExtensionsKt; import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.authentication.AuthenticatorActivity; @@ -39,6 +39,7 @@ import java.io.IOException; import java.net.URI; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -132,42 +133,42 @@ public boolean exists(Account account) { } @Override - @Nullable + @NonNull public Account getCurrentAccount() { Account[] ocAccounts = getAccounts(); - Account defaultAccount = null; ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProviderImpl(context); - SharedPreferences appPreferences = PreferenceManager.getDefaultSharedPreferences(context); String accountName = appPreferences.getString(PREF_SELECT_OC_ACCOUNT, null); - // account validation: the saved account MUST be in the list of ownCloud Accounts known by the AccountManager - if (accountName != null) { - for (Account account : ocAccounts) { - if (account.name.equals(accountName)) { - defaultAccount = account; - break; - } - } + Account defaultAccount = Arrays.stream(ocAccounts) + .filter(account -> account.name.equals(accountName)) + .findFirst() + .orElse(null); + + // take first which is not pending for removal account as fallback + if (defaultAccount == null) { + defaultAccount = Arrays.stream(ocAccounts) + .filter(account -> !arbitraryDataProvider.getBooleanValue(account.name, PENDING_FOR_REMOVAL)) + .findFirst() + .orElse(null); } - if (defaultAccount == null && ocAccounts.length > 0) { - // take first which is not pending for removal account as fallback - for (Account account: ocAccounts) { - boolean pendingForRemoval = arbitraryDataProvider.getBooleanValue(account.name, - PENDING_FOR_REMOVAL); - - if (!pendingForRemoval) { - defaultAccount = account; - break; - } + if (defaultAccount == null) { + if (ocAccounts.length > 0) { + defaultAccount = ocAccounts[0]; + } else { + defaultAccount = getAnonymousAccount(); } } return defaultAccount; } + private Account getAnonymousAccount() { + return new Account("Anonymous", context.getString(R.string.anonymous_account_type)); + } + /** * Temporary solution to convert platform account to user instance. * It takes null and returns null on error to ease error handling @@ -177,8 +178,8 @@ public Account getCurrentAccount() { * @return User instance or null, if conversion failed */ @Nullable - private User createUserFromAccount(@Nullable Account account) { - if (account == null) { + private User createUserFromAccount(@NonNull Account account) { + if (AccountExtensionsKt.isAnonymous(account, context)) { return null; } @@ -260,7 +261,7 @@ public OwnCloudAccount getCurrentOwnCloudAccount() { } @Override - @Nullable + @NonNull public Account getAccountByName(String name) { for (Account account : getAccounts()) { if (account.name.equals(name)) { @@ -268,7 +269,7 @@ public Account getAccountByName(String name) { } } - return null; + return getAnonymousAccount(); } @Override diff --git a/app/src/main/java/com/nextcloud/client/di/AppModule.java b/app/src/main/java/com/nextcloud/client/di/AppModule.java index 472af83d784f..a87b01ee1f99 100644 --- a/app/src/main/java/com/nextcloud/client/di/AppModule.java +++ b/app/src/main/java/com/nextcloud/client/di/AppModule.java @@ -100,8 +100,7 @@ Resources resources(Application application) { @Provides UserAccountManager userAccountManager( Context context, - AccountManager accountManager - ) { + AccountManager accountManager) { return new UserAccountManagerImpl(context, accountManager); } diff --git a/app/src/main/java/com/nextcloud/client/mixins/SessionMixin.kt b/app/src/main/java/com/nextcloud/client/mixins/SessionMixin.kt index 4adff4d6a44b..6cbd5132635e 100644 --- a/app/src/main/java/com/nextcloud/client/mixins/SessionMixin.kt +++ b/app/src/main/java/com/nextcloud/client/mixins/SessionMixin.kt @@ -9,14 +9,12 @@ package com.nextcloud.client.mixins import android.accounts.Account import android.app.Activity -import android.content.ContentResolver import android.content.Intent import android.os.Bundle import com.nextcloud.client.account.User import com.nextcloud.client.account.UserAccountManager -import com.owncloud.android.datamodel.FileDataStorageManager +import com.nextcloud.utils.extensions.isAnonymous import com.owncloud.android.lib.resources.status.OCCapability -import com.owncloud.android.ui.activity.BaseActivity import com.owncloud.android.utils.theme.CapabilityUtils import java.util.Optional @@ -27,36 +25,25 @@ import java.util.Optional * It is an intermediary step facilitating comprehensive rework of * account handling logic. */ -class SessionMixin constructor( +class SessionMixin( private val activity: Activity, - private val contentResolver: ContentResolver, private val accountManager: UserAccountManager ) : ActivityMixin { - - private companion object { - private val TAG = BaseActivity::class.java.simpleName - } - - var currentAccount: Account? = null - private set - var storageManager: FileDataStorageManager? = null + lateinit var currentAccount: Account private set + val capabilities: OCCapability? get() = getUser() .map { CapabilityUtils.getCapability(it, activity) } .orElse(null) - fun setAccount(account: Account?) { - val validAccount = account != null && accountManager.setCurrentOwnCloudAccount(account.name) - if (validAccount) { - currentAccount = account - } else { - swapToDefaultAccount() - } + fun setAccount(account: Account) { + val validAccount = (accountManager.setCurrentOwnCloudAccount(account.name)) - currentAccount?.let { - val storageManager = FileDataStorageManager(getUser().get(), contentResolver) - this.storageManager = storageManager + currentAccount = if (validAccount) { + account + } else { + getDefaultAccount() } } @@ -64,9 +51,12 @@ class SessionMixin constructor( setAccount(user.toPlatformAccount()) } - fun getUser(): Optional = when (val it = this.currentAccount) { - null -> Optional.empty() - else -> accountManager.getUser(it.name) + fun getUser(): Optional { + return if (currentAccount.isAnonymous(activity)) { + Optional.empty() + } else { + accountManager.getUser(currentAccount.name) + } } /** @@ -75,16 +65,14 @@ class SessionMixin constructor( * If no valid ownCloud [Account] exists, then the user is requested * to create a new ownCloud [Account]. */ - private fun swapToDefaultAccount() { - // default to the most recently used account - val newAccount = accountManager.currentAccount - if (newAccount == null) { - // no account available: force account creation - currentAccount = null + private fun getDefaultAccount(): Account { + val defaultAccount = accountManager.currentAccount + + if (defaultAccount.isAnonymous(activity)) { startAccountCreation() - } else { - currentAccount = newAccount } + + return defaultAccount } /** @@ -98,7 +86,7 @@ class SessionMixin constructor( super.onNewIntent(intent) val current = accountManager.currentAccount val currentAccount = this.currentAccount - if (current != null && currentAccount != null && !currentAccount.name.equals(current.name)) { + if (!currentAccount.name.equals(current.name)) { this.currentAccount = current } } @@ -109,9 +97,9 @@ class SessionMixin constructor( */ override fun onRestart() { super.onRestart() - val validAccount = currentAccount != null && accountManager.exists(currentAccount) + val validAccount = accountManager.exists(currentAccount) if (!validAccount) { - swapToDefaultAccount() + getDefaultAccount() } } @@ -120,11 +108,4 @@ class SessionMixin constructor( val account = accountManager.currentAccount setAccount(account) } - - override fun onResume() { - super.onResume() - if (currentAccount == null) { - swapToDefaultAccount() - } - } } diff --git a/app/src/main/java/com/nextcloud/utils/extensions/AccountExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/AccountExtensions.kt new file mode 100644 index 000000000000..c17f93c6f451 --- /dev/null +++ b/app/src/main/java/com/nextcloud/utils/extensions/AccountExtensions.kt @@ -0,0 +1,14 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2024 Your Name + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.utils.extensions + +import android.accounts.Account +import android.content.Context +import com.owncloud.android.R + +fun Account.isAnonymous(context: Context): Boolean = type.equals(context.getString(R.string.anonymous_account_type)) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/BaseActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/BaseActivity.java index fc17209873d8..05ed0a9891d2 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/BaseActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/BaseActivity.java @@ -48,6 +48,7 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab @Inject UserAccountManager accountManager; @Inject AppPreferences preferences; + @Inject FileDataStorageManager fileDataStorageManager; private AppPreferences.Listener onPreferencesChanged = new AppPreferences.Listener() { @Override @@ -63,9 +64,7 @@ public UserAccountManager getUserAccountManager() { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - sessionMixin = new SessionMixin(this, - getContentResolver(), - accountManager); + sessionMixin = new SessionMixin(this, accountManager); mixinRegistry.add(sessionMixin); if (enableAccountHandling) { @@ -174,6 +173,6 @@ public Optional getUser() { } public FileDataStorageManager getStorageManager() { - return sessionMixin.getStorageManager(); + return fileDataStorageManager; } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 63679a057b7b..d3bcdc8e5459 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -30,6 +30,8 @@ Proxy Host Name Proxy Port + AnonymousAccountType + Unable to fetch task types, please check your internet connection. Unable to fetch task list, please check your internet connection. diff --git a/app/src/test/java/com/nextcloud/client/mixins/SessionMixinTest.kt b/app/src/test/java/com/nextcloud/client/mixins/SessionMixinTest.kt index 09ef6e1a163e..135eeb07c31a 100644 --- a/app/src/test/java/com/nextcloud/client/mixins/SessionMixinTest.kt +++ b/app/src/test/java/com/nextcloud/client/mixins/SessionMixinTest.kt @@ -8,9 +8,7 @@ package com.nextcloud.client.mixins import android.app.Activity -import android.content.ContentResolver import com.nextcloud.client.account.UserAccountManager -import junit.framework.Assert.assertNull import org.junit.Before import org.junit.Test import org.mockito.Mock @@ -24,9 +22,6 @@ class SessionMixinTest { @Mock private lateinit var activity: Activity - @Mock - private lateinit var contentResolver: ContentResolver - @Mock private lateinit var userAccountManager: UserAccountManager @@ -38,7 +33,6 @@ class SessionMixinTest { session = spy( SessionMixin( activity, - contentResolver, userAccountManager ) ) @@ -55,15 +49,4 @@ class SessionMixinTest { // account manager receives parent activity verify(userAccountManager).startAccountCreation(same(activity)) } - - @Test - fun `trigger accountCreation on resume when currentAccount is null`() { - // WHEN - // start onResume and currentAccount is null - assertNull(session.currentAccount) - session.onResume() - // THEN - // accountCreation flow is started - verify(session).startAccountCreation() - } }