mirror of
https://github.com/nextcloud/android.git
synced 2024-11-26 07:05:49 +03:00
Merge pull request #5064 from nextcloud/ezaquarii/extract-account-logic-from-base-activity-into-mixin
Extract account logic from BaseActivity into a mixin
This commit is contained in:
commit
4be18adc2d
17 changed files with 478 additions and 169 deletions
|
@ -20,6 +20,8 @@
|
|||
package com.nextcloud.client.account;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.nextcloud.java.util.Optional;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
|
@ -141,4 +143,12 @@ public interface UserAccountManager extends CurrentAccountProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch account registration activity.
|
||||
*
|
||||
* This method returns immediately. Authenticator activity will be launched asynchronously.
|
||||
*
|
||||
* @param activity Activity used to launch authenticator flow via {@link Activity#startActivity(Intent)}
|
||||
*/
|
||||
void startAccountCreation(Activity activity);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package com.nextcloud.client.account;
|
|||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
@ -376,4 +377,15 @@ public class UserAccountManagerImpl implements UserAccountManager {
|
|||
private String getAccountType() {
|
||||
return context.getString(R.string.account_type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startAccountCreation(final Activity activity) {
|
||||
accountManager.addAccount(getAccountType(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
activity,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,5 +28,14 @@ typealias OnErrorCallback = (Throwable) -> Unit
|
|||
* It is provided as an alternative for heavy, platform specific and virtually untestable [android.os.AsyncTask]
|
||||
*/
|
||||
interface AsyncRunner {
|
||||
|
||||
/**
|
||||
* Post a background task and return immediately returning task cancellation interface.
|
||||
*
|
||||
* @param task Task function returning result T; error shall be signalled by throwing an exception.
|
||||
* @param onResult Callback called when task function returns a result
|
||||
* @param onError Callback called when task function throws an exception
|
||||
* @return Cancellable interface, allowing to cancel running task.
|
||||
*/
|
||||
fun <T> post(task: () -> T, onResult: OnResultCallback<T>? = null, onError: OnErrorCallback? = null): Cancellable
|
||||
}
|
||||
|
|
|
@ -19,6 +19,20 @@
|
|||
*/
|
||||
package com.nextcloud.client.core
|
||||
|
||||
/**
|
||||
* Interface allowing cancellation of a running task.
|
||||
* Once must be careful when cancelling a non-idempotent task,
|
||||
* as cancellation does not guarantee a task termination.
|
||||
* One trivial case would be a task finished and cancelled
|
||||
* before result delivery.
|
||||
*
|
||||
* @see [com.nextcloud.client.core.AsyncRunner]
|
||||
*/
|
||||
interface Cancellable {
|
||||
|
||||
/**
|
||||
* Cancel running task. Task termination is not guaranteed, but the result
|
||||
* shall not be delivered.
|
||||
*/
|
||||
fun cancel()
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ package com.nextcloud.client.di;
|
|||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import dagger.android.AndroidInjection;
|
||||
|
@ -72,4 +71,3 @@ public class ActivityInjector implements Application.ActivityLifecycleCallbacks
|
|||
// not needed
|
||||
}
|
||||
}
|
||||
|
||||
|
|
40
src/main/java/com/nextcloud/client/mixins/ActivityMixin.kt
Normal file
40
src/main/java/com/nextcloud/client/mixins/ActivityMixin.kt
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Chris Narkiewicz
|
||||
* Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* Copyright (C) 2020 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.nextcloud.client.mixins
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
|
||||
/**
|
||||
* Interface allowing to implement part of [android.app.Activity] logic as
|
||||
* a mix-in.
|
||||
*/
|
||||
interface ActivityMixin {
|
||||
fun onNewIntent(intent: Intent) { /* no-op */ }
|
||||
fun onSaveInstanceState(outState: Bundle) { /* no-op */ }
|
||||
fun onCreate(savedInstanceState: Bundle?) { /* no-op */ }
|
||||
fun onRestart() { /* no-op */ }
|
||||
fun onStart() { /* no-op */ }
|
||||
fun onResume() { /* no-op */ }
|
||||
fun onPause() { /* no-op */ }
|
||||
fun onStop() { /* no-op */ }
|
||||
fun onDestroy() { /* no-op */ }
|
||||
}
|
88
src/main/java/com/nextcloud/client/mixins/MixinRegistry.kt
Normal file
88
src/main/java/com/nextcloud/client/mixins/MixinRegistry.kt
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Chris Narkiewicz
|
||||
* Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* Copyright (C) 2020 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.nextcloud.client.mixins
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
|
||||
/**
|
||||
* Mix-in registry allows forwards lifecycle calls to all
|
||||
* registered mix-ins.
|
||||
*
|
||||
* Once instantiated, all [android.app.Activity] lifecycle methods
|
||||
* must call relevant registry companion methods.
|
||||
*
|
||||
* Calling the registry from [android.app.Application.ActivityLifecycleCallbacks] is
|
||||
* not possible as not all callbacks are supported by this interface.
|
||||
*/
|
||||
class MixinRegistry : ActivityMixin {
|
||||
|
||||
private val mixins = mutableListOf<ActivityMixin>()
|
||||
|
||||
fun add(vararg mixins: ActivityMixin) {
|
||||
mixins.forEach { this.mixins.add(it) }
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
mixins.forEach { it.onNewIntent(intent) }
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mixins.forEach { it.onSaveInstanceState(outState) }
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
mixins.forEach { it.onCreate(savedInstanceState) }
|
||||
}
|
||||
|
||||
override fun onRestart() {
|
||||
super.onRestart()
|
||||
mixins.forEach { it.onRestart() }
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mixins.forEach { it.onStart() }
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mixins.forEach { it.onResume() }
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mixins.forEach { it.onPause() }
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mixins.forEach { it.onStop() }
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mixins.forEach { it.onDestroy() }
|
||||
}
|
||||
}
|
10
src/main/java/com/nextcloud/client/mixins/Package.md
Normal file
10
src/main/java/com/nextcloud/client/mixins/Package.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Package com.nextcloud.client.mixins
|
||||
|
||||
This package provides utilities and interfaces
|
||||
allowing implementation of UI logic as mix-ins.
|
||||
|
||||
Mix-ins allow encapsulation of non-visual logic
|
||||
as classes facilitating composition over inheritance.
|
||||
|
||||
For more information about mix-in concept, please
|
||||
refer to [article on Wikipedia](https://en.wikipedia.org/wiki/Mixin).
|
133
src/main/java/com/nextcloud/client/mixins/SessionMixin.kt
Normal file
133
src/main/java/com/nextcloud/client/mixins/SessionMixin.kt
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Chris Narkiewicz
|
||||
* Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* Copyright (C) 2020 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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.nextcloud.java.util.Optional
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager
|
||||
import com.owncloud.android.lib.resources.status.OCCapability
|
||||
import com.owncloud.android.ui.activity.BaseActivity
|
||||
|
||||
/**
|
||||
* Session mixin collects all account / user handling logic currently
|
||||
* spread over various activities.
|
||||
*
|
||||
* It is an intermediary step facilitating comprehensive rework of
|
||||
* account handling logic.
|
||||
*/
|
||||
class SessionMixin constructor(
|
||||
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
|
||||
private set
|
||||
var capabilities: OCCapability? = null
|
||||
private set
|
||||
|
||||
fun setAccount(account: Account?) {
|
||||
val validAccount = account != null && accountManager.setCurrentOwnCloudAccount(account.name)
|
||||
if (validAccount) {
|
||||
currentAccount = account
|
||||
} else {
|
||||
swapToDefaultAccount()
|
||||
}
|
||||
|
||||
currentAccount?.let {
|
||||
val storageManager = FileDataStorageManager(currentAccount, contentResolver)
|
||||
this.storageManager = storageManager
|
||||
this.capabilities = storageManager.getCapability(it.name)
|
||||
}
|
||||
}
|
||||
|
||||
fun setUser(user: User) {
|
||||
setAccount(user.toPlatformAccount())
|
||||
}
|
||||
|
||||
fun getUser(): Optional<User> = when (val it = this.currentAccount) {
|
||||
null -> Optional.empty()
|
||||
else -> accountManager.getUser(it.name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to swap the current ownCloud [Account] for other valid and existing.
|
||||
*
|
||||
* 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
|
||||
startAccountCreation()
|
||||
} else {
|
||||
currentAccount = newAccount
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the account creation activity.
|
||||
*/
|
||||
fun startAccountCreation() {
|
||||
accountManager.startAccountCreation(activity)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
val current = accountManager.currentAccount
|
||||
val currentAccount = this.currentAccount
|
||||
if (current != null && currentAccount != null && !currentAccount.name.equals(current.name)) {
|
||||
this.currentAccount = current
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Since ownCloud {@link Account} can be managed from the system setting menu, the existence of the {@link
|
||||
* Account} associated to the instance must be checked every time it is restarted.
|
||||
*/
|
||||
override fun onRestart() {
|
||||
super.onRestart()
|
||||
val validAccount = currentAccount != null && accountManager.exists(currentAccount)
|
||||
if (!validAccount) {
|
||||
swapToDefaultAccount()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val account = accountManager.currentAccount
|
||||
setAccount(account)
|
||||
}
|
||||
}
|
|
@ -72,8 +72,6 @@ public class FirstRunActivity extends BaseActivity implements ViewPager.OnPageCh
|
|||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
enableAccountHandling = false;
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.first_run_activity);
|
||||
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
package com.owncloud.android.ui.activity;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountManagerCallback;
|
||||
import android.accounts.AccountManagerFuture;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
||||
import com.nextcloud.client.account.User;
|
||||
import com.nextcloud.client.account.UserAccountManager;
|
||||
import com.nextcloud.client.di.Injectable;
|
||||
import com.nextcloud.client.mixins.MixinRegistry;
|
||||
import com.nextcloud.client.mixins.SessionMixin;
|
||||
import com.nextcloud.client.preferences.AppPreferences;
|
||||
import com.nextcloud.client.preferences.DarkMode;
|
||||
import com.nextcloud.java.util.Optional;
|
||||
import com.owncloud.android.MainApp;
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
@ -33,27 +29,14 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab
|
|||
|
||||
private static final String TAG = BaseActivity.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* ownCloud {@link Account} where the main {@link OCFile} handled by the activity is located.
|
||||
*/
|
||||
private Account currentAccount;
|
||||
|
||||
/**
|
||||
* Capabilities of the server where {@link #currentAccount} lives.
|
||||
*/
|
||||
private OCCapability capabilities;
|
||||
|
||||
/**
|
||||
* Access point to the cached database for the current ownCloud {@link Account}.
|
||||
*/
|
||||
private FileDataStorageManager storageManager;
|
||||
|
||||
/**
|
||||
* Tracks whether the activity should be recreate()'d after a theme change
|
||||
*/
|
||||
private boolean themeChangePending;
|
||||
private boolean paused;
|
||||
protected boolean enableAccountHandling = true;
|
||||
|
||||
private MixinRegistry mixinRegistry = new MixinRegistry();
|
||||
private SessionMixin sessionMixin;
|
||||
|
||||
@Inject UserAccountManager accountManager;
|
||||
@Inject AppPreferences preferences;
|
||||
|
@ -72,11 +55,11 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab
|
|||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (enableAccountHandling) {
|
||||
Account account = accountManager.getCurrentAccount();
|
||||
setAccount(account, false);
|
||||
}
|
||||
sessionMixin = new SessionMixin(this,
|
||||
getContentResolver(),
|
||||
accountManager);
|
||||
mixinRegistry.add(sessionMixin);
|
||||
mixinRegistry.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,18 +71,21 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab
|
|||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mixinRegistry.onDestroy();
|
||||
preferences.removeListener(onPreferencesChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mixinRegistry.onPause();
|
||||
paused = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mixinRegistry.onResume();
|
||||
paused = false;
|
||||
|
||||
if (themeChangePending) {
|
||||
|
@ -110,28 +96,14 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab
|
|||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
|
||||
Log_OC.v(TAG, "onNewIntent() start");
|
||||
Account current = accountManager.getCurrentAccount();
|
||||
if (current != null && currentAccount != null && !currentAccount.name.equals(current.name)) {
|
||||
currentAccount = current;
|
||||
}
|
||||
Log_OC.v(TAG, "onNewIntent() stop");
|
||||
mixinRegistry.onNewIntent(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Since ownCloud {@link Account}s can be managed from the system setting menu, the existence of the {@link
|
||||
* Account} associated to the instance must be checked every time it is restarted.
|
||||
*/
|
||||
@Override
|
||||
protected void onRestart() {
|
||||
Log_OC.v(TAG, "onRestart() start");
|
||||
super.onRestart();
|
||||
boolean validAccount = currentAccount != null && accountManager.exists(currentAccount);
|
||||
if (!validAccount) {
|
||||
swapToDefaultAccount();
|
||||
}
|
||||
Log_OC.v(TAG, "onRestart() end");
|
||||
mixinRegistry.onRestart();
|
||||
}
|
||||
|
||||
private void onThemeSettingsModeChanged() {
|
||||
|
@ -152,56 +124,18 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab
|
|||
*/
|
||||
@Deprecated
|
||||
protected void setAccount(Account account, boolean savedAccount) {
|
||||
boolean validAccount = account != null && accountManager.setCurrentOwnCloudAccount(account.name);
|
||||
if (validAccount) {
|
||||
currentAccount = account;
|
||||
} else {
|
||||
swapToDefaultAccount();
|
||||
}
|
||||
|
||||
if(currentAccount != null) {
|
||||
storageManager = new FileDataStorageManager(currentAccount, getContentResolver());
|
||||
capabilities = storageManager.getCapability(currentAccount.name);
|
||||
}
|
||||
sessionMixin.setAccount(account);
|
||||
}
|
||||
|
||||
protected void setUser(User user) {
|
||||
setAccount(user.toPlatformAccount(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to swap the current ownCloud {@link Account} for other valid and existing.
|
||||
*
|
||||
* If no valid ownCloud {@link Account} exists, then the user is requested
|
||||
* to create a new ownCloud {@link Account}.
|
||||
*/
|
||||
protected void swapToDefaultAccount() {
|
||||
// default to the most recently used account
|
||||
Account newAccount = accountManager.getCurrentAccount();
|
||||
|
||||
if (newAccount == null) {
|
||||
/// no account available: force account creation
|
||||
createAccount(true);
|
||||
} else {
|
||||
currentAccount = newAccount;
|
||||
}
|
||||
sessionMixin.setUser(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the account creation activity.
|
||||
*
|
||||
* @param mandatoryCreation When 'true', if an account is not created by the user, the app will be closed.
|
||||
* To use when no ownCloud account is available.
|
||||
*/
|
||||
protected void createAccount(boolean mandatoryCreation) {
|
||||
AccountManager am = AccountManager.get(getApplicationContext());
|
||||
am.addAccount(MainApp.getAccountType(this),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
this,
|
||||
new AccountCreationCallback(mandatoryCreation),
|
||||
new Handler());
|
||||
protected void startAccountCreation() {
|
||||
sessionMixin.startAccountCreation();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,7 +145,7 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab
|
|||
* set yet.
|
||||
*/
|
||||
public OCCapability getCapabilities() {
|
||||
return capabilities;
|
||||
return sessionMixin.getCapabilities();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,76 +156,14 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab
|
|||
* is located.
|
||||
*/
|
||||
public Account getAccount() {
|
||||
return currentAccount;
|
||||
return sessionMixin.getCurrentAccount();
|
||||
}
|
||||
|
||||
public Optional<User> getUser() {
|
||||
if (currentAccount != null) {
|
||||
return accountManager.getUser(currentAccount.name);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
return sessionMixin.getUser();
|
||||
}
|
||||
|
||||
public FileDataStorageManager getStorageManager() {
|
||||
return storageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that gets called when a new account has been successfully created.
|
||||
*
|
||||
* @param future
|
||||
*/
|
||||
protected void onAccountCreationSuccessful(AccountManagerFuture<Bundle> future) {
|
||||
// no special handling in base activity
|
||||
Log_OC.d(TAG,"onAccountCreationSuccessful");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class handling a callback from the {@link AccountManager} after the creation of
|
||||
* a new ownCloud {@link Account} finished, successfully or not.
|
||||
*/
|
||||
public class AccountCreationCallback implements AccountManagerCallback<Bundle> {
|
||||
|
||||
boolean mMandatoryCreation;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param mandatoryCreation When 'true', if an account was not created, the app is closed.
|
||||
*/
|
||||
public AccountCreationCallback(boolean mandatoryCreation) {
|
||||
mMandatoryCreation = mandatoryCreation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(AccountManagerFuture<Bundle> future) {
|
||||
boolean accountWasSet = false;
|
||||
if (future != null) {
|
||||
try {
|
||||
Bundle result;
|
||||
result = future.getResult();
|
||||
String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
|
||||
String type = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
|
||||
if (accountManager.setCurrentOwnCloudAccount(name)) {
|
||||
setAccount(new Account(name, type), false);
|
||||
accountWasSet = true;
|
||||
}
|
||||
|
||||
onAccountCreationSuccessful(future);
|
||||
} catch (OperationCanceledException e) {
|
||||
Log_OC.d(TAG, "Account creation canceled");
|
||||
|
||||
} catch (Exception e) {
|
||||
Log_OC.e(TAG, "Account creation finished in exception: ", e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Log_OC.e(TAG, "Account creation callback with null bundle");
|
||||
}
|
||||
if (mMandatoryCreation && !accountWasSet) {
|
||||
moveTaskToBack(true);
|
||||
}
|
||||
}
|
||||
return sessionMixin.getStorageManager();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ package com.owncloud.android.ui.activity;
|
|||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountManagerFuture;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -510,7 +509,7 @@ public abstract class DrawerActivity extends ToolbarActivity
|
|||
firstRunIntent.putExtra(FirstRunActivity.EXTRA_ALLOW_CLOSE, true);
|
||||
startActivity(firstRunIntent);
|
||||
} else {
|
||||
createAccount(false);
|
||||
startAccountCreation();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1351,13 +1350,6 @@ public abstract class DrawerActivity extends ToolbarActivity
|
|||
*/
|
||||
protected abstract void restart();
|
||||
|
||||
@Override
|
||||
protected void onAccountCreationSuccessful(AccountManagerFuture<Bundle> future) {
|
||||
super.onAccountCreationSuccessful(future);
|
||||
updateAccountList();
|
||||
restart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of users suitable for displaying in navigation drawer header.
|
||||
* First item is always current {@link User}. Remaining items are other
|
||||
|
|
|
@ -230,12 +230,10 @@ public class FileDisplayActivity extends FileActivity
|
|||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
Log_OC.v(TAG, "onCreate() start");
|
||||
|
||||
// Set the default theme to replace the launch screen theme.
|
||||
setTheme(R.style.Theme_ownCloud_Toolbar_Drawer);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
/// Load of saved instance state
|
||||
if (savedInstanceState != null) {
|
||||
mWaitingToPreview = savedInstanceState.getParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW);
|
||||
|
|
|
@ -266,7 +266,7 @@ public class ManageAccountsActivity extends FileActivity implements AccountListA
|
|||
}
|
||||
|
||||
@Override
|
||||
public void createAccount() {
|
||||
public void startAccountCreation() {
|
||||
AccountManager am = AccountManager.get(getApplicationContext());
|
||||
am.addAccount(MainApp.getAccountType(this),
|
||||
null,
|
||||
|
|
|
@ -158,7 +158,7 @@ public class AccountListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
|
|||
if (isProviderOrOwnInstallationVisible) {
|
||||
actionView.setOnClickListener(v -> accountListAdapterListener.showFirstRunActivity());
|
||||
} else {
|
||||
actionView.setOnClickListener(v -> accountListAdapterListener.createAccount());
|
||||
actionView.setOnClickListener(v -> accountListAdapterListener.startAccountCreation());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,7 @@ public class AccountListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
|
|||
|
||||
void showFirstRunActivity();
|
||||
|
||||
void createAccount();
|
||||
void startAccountCreation();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Chris Narkiewicz
|
||||
* Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* Copyright (C) 2020 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.nextcloud.client.mixins
|
||||
|
||||
import android.os.Bundle
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.same
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito
|
||||
|
||||
class MixinRegistryTest {
|
||||
|
||||
@Test
|
||||
fun `callbacks are invoked in order of calls and mixin registration`() {
|
||||
// GIVEN
|
||||
// registry has 2 mixins registered
|
||||
val registry = MixinRegistry()
|
||||
val firstMixin = mock<ActivityMixin>()
|
||||
val secondMixin = mock<ActivityMixin>()
|
||||
registry.add(firstMixin, secondMixin)
|
||||
|
||||
// WHEN
|
||||
// all lifecycle callbacks are invoked
|
||||
val bundle = mock<Bundle>()
|
||||
registry.onCreate(bundle)
|
||||
registry.onStart()
|
||||
registry.onResume()
|
||||
registry.onPause()
|
||||
registry.onStop()
|
||||
registry.onDestroy()
|
||||
|
||||
// THEN
|
||||
// callbacks are invoked in order of mixin registration
|
||||
// callbacks are invoked in order of registry calls
|
||||
Mockito.inOrder(firstMixin, secondMixin).apply {
|
||||
verify(firstMixin).onCreate(same(bundle))
|
||||
verify(secondMixin).onCreate(same(bundle))
|
||||
verify(firstMixin).onStart()
|
||||
verify(secondMixin).onStart()
|
||||
verify(firstMixin).onResume()
|
||||
verify(secondMixin).onResume()
|
||||
verify(firstMixin).onPause()
|
||||
verify(secondMixin).onPause()
|
||||
verify(firstMixin).onStop()
|
||||
verify(secondMixin).onStop()
|
||||
verify(firstMixin).onDestroy()
|
||||
verify(secondMixin).onDestroy()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Chris Narkiewicz
|
||||
* Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* Copyright (C) 2020 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.nextcloud.client.mixins
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ContentResolver
|
||||
import com.nextcloud.client.account.UserAccountManager
|
||||
import com.nhaarman.mockitokotlin2.verify
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.same
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
class SessionMixinTest {
|
||||
|
||||
@Mock
|
||||
private lateinit var activity: Activity
|
||||
|
||||
@Mock
|
||||
private lateinit var contentResolver: ContentResolver
|
||||
|
||||
@Mock
|
||||
private lateinit var userAccountManager: UserAccountManager
|
||||
|
||||
private lateinit var session: SessionMixin
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
session = SessionMixin(
|
||||
activity,
|
||||
contentResolver,
|
||||
userAccountManager
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `start account creation`() {
|
||||
// WHEN
|
||||
// start account creation flow
|
||||
session.startAccountCreation()
|
||||
|
||||
// THEN
|
||||
// start is delegated to account manager
|
||||
// account manager receives parent activity
|
||||
verify(userAccountManager).startAccountCreation(same(activity))
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue