Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ This conversion was the hardest one so far, because the Activity extended `FileA
- Host stays a `DrawerActivity`. The credential flow moves into the
fragment.
- To avoid copying `FileActivity` logic, `ui/helpers/CredentialsUpdateHelper.kt` was
extracted. `FileActivity.performCredentialsUpdate`, `CheckRemoteWipeTask` and the fragment
all use it.
extracted. `CheckRemoteWipeTask` (used by `FileActivity`) and the fragment both use it.

## Resulting files

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ navigator screen a `FileActivity` would bind `OperationsService` for all of them
|---|---|
| `fileOperationsHelper.*` (queues operations on `OperationsService`) | Run the `RemoteOperation`/`SyncOperation` directly in `lifecycleScope` on `Dispatchers.IO` with a client for the right user |
| `onRemoteOperationFinish(op, result)` override | Handle the result inline after the coroutine returns |
| `requestCredentialsUpdate(account)` → `CheckRemoteWipeTask` → `performCredentialsUpdate` | `CredentialsUpdateHelper` (`isRemoteWipeRequested`, `invalidateCredentials`, `createUpdateCredentialsIntent`) + `registerForActivityResult` |
| `onActivityResult(REQUEST_CODE__UPDATE_CREDENTIALS, RESULT_OK)` | the `ActivityResultLauncher` callback |
| `requestCredentialsUpdate(account)` → `CheckRemoteWipeTask.execute` (launches `AuthenticatorActivity` through its own `ActivityResultLauncher`) | `CredentialsUpdateHelper` (`isRemoteWipeRequested`, `invalidateCredentials`, `createUpdateCredentialsIntent`) + `registerForActivityResult` |
| Reacting to the credentials update result | the `ActivityResultLauncher` callback |
| `showLoadingDialog` / `dismissLoadingDialog` | `LoadingDialog.newInstance(msg).show(childFragmentManager, TAG)` and `dismissAllowingStateLoss()` |
| `EXTRA_USER` → `setUser` in `onCreate` | fragment reads `activity?.intent` and calls `navigatorActivity?.setUser` |
| `EXTRA_FILE` → `file` | read it in the fragment if it is used, otherwise drop it from the callers |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@
import com.owncloud.android.ui.fragment.albums.AlbumsFragment;
import com.owncloud.android.ui.fragment.filesRepository.FilesRepository;
import com.owncloud.android.ui.fragment.filesRepository.RemoteFilesRepository;
import com.owncloud.android.ui.helpers.CredentialsUpdateHelper;
import com.owncloud.android.ui.helpers.FileOperationsHelper;
import com.owncloud.android.ui.navigation.model.ActionBarStyle;
import com.owncloud.android.ui.preview.media.PreviewMediaActivity;
Expand All @@ -103,7 +102,6 @@
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.lang.ref.WeakReference;
import java.util.ArrayList;

import javax.inject.Inject;
Expand Down Expand Up @@ -142,8 +140,7 @@ public abstract class FileActivity extends DrawerActivity
private static final String KEY_WAITING_FOR_OP_ID = "WAITING_FOR_OP_ID";
private static final String KEY_ACTION_BAR_TITLE = "ACTION_BAR_TITLE";

public static final int REQUEST_CODE__UPDATE_CREDENTIALS = 0;
public static final int REQUEST_CODE__LAST_SHARED = REQUEST_CODE__UPDATE_CREDENTIALS;
public static final int REQUEST_CODE__LAST_SHARED = 0;

/* Dialog tags */
private static final String DIALOG_UNTRUSTED_CERT = "DIALOG_UNTRUSTED_CERT";
Expand Down Expand Up @@ -186,6 +183,8 @@ public abstract class FileActivity extends DrawerActivity
@Inject
ArbitraryDataProvider arbitraryDataProvider;

private final CheckRemoteWipeTask checkRemoteWipeTask = new CheckRemoteWipeTask(this);

private FilesRepository filesRepository;

@Override
Expand Down Expand Up @@ -462,18 +461,7 @@ protected void requestCredentialsUpdate(Account account) {
account = getAccount();
}

new CheckRemoteWipeTask(backgroundJobManager, account, new WeakReference<>(this)).execute();
}

public void performCredentialsUpdate(Account account) {
final var credentialsUpdateHelper = new CredentialsUpdateHelper(this);
try {
credentialsUpdateHelper.invalidateCredentials(account);
startActivityForResult(credentialsUpdateHelper.createUpdateCredentialsIntent(account),
REQUEST_CODE__UPDATE_CREDENTIALS);
} catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
SnackbarUtil.show(this, R.string.auth_account_does_not_exist);
}
checkRemoteWipeTask.execute(account, backgroundJobManager);
}

/**
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.owncloud.android.ui.asynctasks

import android.accounts.Account
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.WorkerThread
import androidx.lifecycle.lifecycleScope
import com.nextcloud.client.jobs.BackgroundJobManager
import com.nextcloud.utils.extensions.isActive
import com.nextcloud.utils.SnackbarUtil
import com.owncloud.android.R
import com.owncloud.android.lib.common.accounts.AccountUtils
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.ui.activity.FileActivity
import com.owncloud.android.ui.helpers.CredentialsUpdateHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class CheckRemoteWipeTask(private val fileActivity: FileActivity) {
companion object {
private const val TAG = "CheckRemoteWipeTask"
}

private val credentialsUpdateHelper = CredentialsUpdateHelper(fileActivity)

private val credentialsUpdateLauncher =
fileActivity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { }

fun execute(account: Account, backgroundJobManager: BackgroundJobManager): Job =
fileActivity.lifecycleScope.launch {
val isWipeRequested = withContext(Dispatchers.IO + NonCancellable) {
startAccountRemovalIfWipeRequested(account, backgroundJobManager)
}

if (isWipeRequested || !fileActivity.isActive()) {
return@launch
}

performCredentialsUpdate(account)
}

private fun performCredentialsUpdate(account: Account) {
try {
credentialsUpdateHelper.invalidateCredentials(account)
credentialsUpdateLauncher.launch(credentialsUpdateHelper.createUpdateCredentialsIntent(account))
} catch (_: AccountUtils.AccountNotFoundException) {
SnackbarUtil.show(fileActivity, R.string.auth_account_does_not_exist)
}
}

@WorkerThread
private fun startAccountRemovalIfWipeRequested(
account: Account,
backgroundJobManager: BackgroundJobManager
): Boolean {
if (!credentialsUpdateHelper.isRemoteWipeRequested(account)) {
Log_OC.e(TAG, "Check for remote wipe not needed -> update credentials")
return false
}

backgroundJobManager.startAccountRemovalJob(account.name, true)
return true
}
}
Loading