From 56c3046c8014bf61a3f3ad5aff97c319dff47213 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 15:46:04 +0200 Subject: [PATCH 1/9] fix: handle slow internet connection better for fetching shares Signed-off-by: alperozturk # Conflicts: # build.gradle --- .../ui/fragment/OCFileListFragment.java | 13 ++- .../ui/fragment/OCFileListSearchAsyncTask.kt | 83 ----------------- .../ui/fragment/OCFileListSearchTask.kt | 92 +++++++++++++++++++ .../android/ui/fragment/SharedListFragment.kt | 3 +- 4 files changed, 100 insertions(+), 91 deletions(-) delete mode 100644 app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchAsyncTask.kt create mode 100644 app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index d640501187ec..aec1f7b47c96 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -225,7 +225,7 @@ public class OCFileListFragment extends ExtendedListFragment implements protected SearchType currentSearchType; protected boolean searchFragment; protected SearchEvent searchEvent; - protected AsyncTask remoteOperationAsyncTask; + private OCFileListSearchTask searchTask; protected String mLimitToMimeType; private FloatingActionButton mFabMain; public static boolean isMultipleFileSelectedForCopyOrMove = false; @@ -356,8 +356,8 @@ public void onDetach() { setOnRefreshListener(null); mContainerActivity = null; - if (remoteOperationAsyncTask != null) { - remoteOperationAsyncTask.cancel(true); + if (searchTask != null) { + searchTask.cancel(); } super.onDetach(); } @@ -1915,7 +1915,7 @@ protected void handleSearchEvent(SearchEvent event) { } // avoid calling api multiple times if async task is already executing - if (remoteOperationAsyncTask != null && remoteOperationAsyncTask.getStatus() != AsyncTask.Status.FINISHED) { + if (searchTask != null && !searchTask.isFinished()) { if (searchEvent != null) { Log_OC.d(TAG, "OCFileListSearchAsyncTask already running skipping new api call for search event: " + searchEvent.getSearchType()); } @@ -1950,9 +1950,8 @@ protected void handleSearchEvent(SearchEvent event) { final RemoteOperation remoteOperation = getSearchRemoteOperation(currentUser, event); - remoteOperationAsyncTask = new OCFileListSearchAsyncTask(mContainerActivity, this, remoteOperation, currentUser, event); - - remoteOperationAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + searchTask = new OCFileListSearchTask(mContainerActivity, this, remoteOperation, currentUser, event); + searchTask.execute(); } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchAsyncTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchAsyncTask.kt deleted file mode 100644 index 75f12306f6bb..000000000000 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchAsyncTask.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2022 Álvaro Brey - * SPDX-FileCopyrightText: 2022 Nextcloud GmbH - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -package com.owncloud.android.ui.fragment - -import android.annotation.SuppressLint -import android.os.AsyncTask -import android.os.Handler -import android.os.Looper -import com.nextcloud.client.account.User -import com.owncloud.android.datamodel.FileDataStorageManager -import com.owncloud.android.lib.common.operations.RemoteOperation -import com.owncloud.android.lib.common.operations.RemoteOperationResult -import com.owncloud.android.ui.events.SearchEvent -import java.lang.ref.WeakReference - -class OCFileListSearchAsyncTask( - containerActivity: FileFragment.ContainerActivity, - fragment: OCFileListFragment, - private val remoteOperation: RemoteOperation>, - private val currentUser: User, - private val event: SearchEvent -) : AsyncTask() { - private val activityReference: WeakReference = WeakReference(containerActivity) - private val fragmentReference: WeakReference = WeakReference(fragment) - - private val fileDataStorageManager: FileDataStorageManager? - get() = activityReference.get()?.storageManager - - private fun RemoteOperationResult.hasSuccessfulResult() = this.isSuccess && this.resultData != null - - override fun onPreExecute() { - fragmentReference.get()?.let { fragment -> - Handler(Looper.getMainLooper()).post { - fragment.setEmptyListMessage(EmptyListState.LOADING) - } - } - } - - override fun doInBackground(vararg voids: Void): Boolean { - val fragment = fragmentReference.get() - if (fragment?.context == null || isCancelled) { - return java.lang.Boolean.FALSE - } - - fragment.setTitle() - lateinit var remoteOperationResult: RemoteOperationResult> - try { - remoteOperationResult = remoteOperation.execute(currentUser, fragment.context) - } catch (_: UnsupportedOperationException) { - remoteOperationResult = remoteOperation.executeNextcloudClient(currentUser, fragment.requireContext()) - } - - if (remoteOperationResult.hasSuccessfulResult() && !isCancelled && fragment.searchFragment) { - fragment.searchEvent = event - if (remoteOperationResult.resultData.isNullOrEmpty()) { - fragment.setEmptyView(event) - } else { - fragment.adapter.setData( - remoteOperationResult.resultData, - fragment.currentSearchType, - fileDataStorageManager, - fragment.mFile, - true - ) - } - } - return remoteOperationResult.isSuccess - } - - @SuppressLint("NotifyDataSetChanged") - override fun onPostExecute(bool: Boolean) { - fragmentReference.get()?.let { fragment -> - if (!isCancelled) { - fragment.adapter.notifyDataSetChanged() - } - } - } -} diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt new file mode 100644 index 000000000000..686b3ff68c2e --- /dev/null +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -0,0 +1,92 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2025 Alper Ozturk + * SPDX-FileCopyrightText: 2022 Álvaro Brey + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +package com.owncloud.android.ui.fragment + +import android.annotation.SuppressLint +import androidx.lifecycle.lifecycleScope +import com.nextcloud.client.account.User +import com.owncloud.android.datamodel.FileDataStorageManager +import com.owncloud.android.lib.common.operations.RemoteOperation +import com.owncloud.android.lib.common.operations.RemoteOperationResult +import com.owncloud.android.ui.events.SearchEvent +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.lang.ref.WeakReference + +@SuppressLint("NotifyDataSetChanged") +class OCFileListSearchTask( + containerActivity: FileFragment.ContainerActivity, + fragment: OCFileListFragment, + private val remoteOperation: RemoteOperation>, + private val currentUser: User, + private val event: SearchEvent +) { + private val activityReference: WeakReference = WeakReference(containerActivity) + private val fragmentReference: WeakReference = WeakReference(fragment) + + private val fileDataStorageManager: FileDataStorageManager? + get() = activityReference.get()?.storageManager + + private fun RemoteOperationResult.hasSuccessfulResult() = this.isSuccess && this.resultData != null + + private var job: Job? = null + + @Suppress("TooGenericExceptionCaught", "DEPRECATION") + fun execute() { + fragmentReference.get()?.let { fragment -> + job = fragment.lifecycleScope.launch(Dispatchers.IO) { + withContext(Dispatchers.Main) { + fragment.setEmptyListMessage(EmptyListState.LOADING) + } + + val result = if (!isActive) { + false + } else { + fragment.setTitle() + lateinit var remoteOperationResult: RemoteOperationResult> + try { + remoteOperationResult = remoteOperation.execute(currentUser, fragment.requireContext()) + } catch (_: Exception) { + remoteOperationResult = + remoteOperation.executeNextcloudClient(currentUser, fragment.requireContext()) + } + + if (remoteOperationResult.hasSuccessfulResult() && isActive && fragment.searchFragment) { + fragment.searchEvent = event + if (remoteOperationResult.resultData.isNullOrEmpty()) { + fragment.setEmptyView(event) + } else { + fragment.adapter.setData( + remoteOperationResult.resultData, + fragment.currentSearchType, + fileDataStorageManager, + fragment.mFile, + true + ) + } + } + remoteOperationResult.isSuccess + } + + withContext(Dispatchers.Main) { + if (result && isActive) { + fragment.adapter.notifyDataSetChanged() + } + } + } + } + } + + fun cancel() = job?.cancel(null) + + fun isFinished(): Boolean = job?.isCompleted == true +} diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt b/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt index 6c8692129e22..1e59e3fac201 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt @@ -14,6 +14,7 @@ import androidx.lifecycle.lifecycleScope import com.nextcloud.client.account.User import com.nextcloud.client.di.Injectable import com.nextcloud.client.logger.Logger +import com.nextcloud.common.SessionTimeOut import com.owncloud.android.R import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.operations.RemoteOperation @@ -68,7 +69,7 @@ class SharedListFragment : } override fun getSearchRemoteOperation(currentUser: User?, event: SearchEvent?): RemoteOperation<*> = - GetSharesRemoteOperation() + GetSharesRemoteOperation(false, SessionTimeOut(60000, 60000)) @Suppress("DEPRECATION") private suspend fun fetchFileData(partialFile: OCFile): OCFile? = withContext(Dispatchers.IO) { From 3af62bf6e342da09cbd3dc60500d5973626a095a Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 15:49:22 +0200 Subject: [PATCH 2/9] add: new empty list type Signed-off-by: alperozturk # Conflicts: # app/src/main/res/values/strings.xml --- .../owncloud/android/ui/fragment/ExtendedListFragment.kt | 8 ++++++++ .../owncloud/android/ui/fragment/OCFileListSearchTask.kt | 2 ++ .../java/com/owncloud/android/ui/fragment/SearchType.kt | 3 ++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt b/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt index f30d627f942d..42d5a4d6a844 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt @@ -707,6 +707,14 @@ open class ExtendedListFragment : true ) } + EmptyListState.ERROR -> { + setMessageForEmptyList( + R.string.file_list_error_headline, + R.string.file_list_error_description, + R.drawable.ic_synchronizing_error, + true + ) + } else -> { setMessageForEmptyList( R.string.file_list_empty_headline, diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt index 686b3ff68c2e..c6cbbd6f3793 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -80,6 +80,8 @@ class OCFileListSearchTask( withContext(Dispatchers.Main) { if (result && isActive) { fragment.adapter.notifyDataSetChanged() + } else { + fragment.setEmptyListMessage(EmptyListState.ERROR) } } } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/SearchType.kt b/app/src/main/java/com/owncloud/android/ui/fragment/SearchType.kt index 36c1e6f6ace0..4e27e0222e17 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/SearchType.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/SearchType.kt @@ -32,5 +32,6 @@ enum class EmptyListState : Parcelable { ADD_FOLDER, ONLY_ON_DEVICE, LOCAL_FILE_LIST_EMPTY_FILE, - LOCAL_FILE_LIST_EMPTY_FOLDER + LOCAL_FILE_LIST_EMPTY_FOLDER, + ERROR } From b0123c905c416a081632c5a3ac597e20661927ab Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 16:32:23 +0200 Subject: [PATCH 3/9] add: task timeout Signed-off-by: alperozturk --- .../ui/fragment/ExtendedListFragment.kt | 2 +- .../ui/fragment/OCFileListFragment.java | 6 +- .../ui/fragment/OCFileListSearchTask.kt | 56 ++++++++++--------- .../android/ui/fragment/SharedListFragment.kt | 3 +- 4 files changed, 36 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt b/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt index 42d5a4d6a844..cb56d08733ad 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt @@ -712,7 +712,7 @@ open class ExtendedListFragment : R.string.file_list_error_headline, R.string.file_list_error_description, R.drawable.ic_synchronizing_error, - true + false ) } else -> { diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index aec1f7b47c96..d73729df5b64 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -1914,7 +1914,7 @@ protected void handleSearchEvent(SearchEvent event) { return; } - // avoid calling api multiple times if async task is already executing + // avoid calling api multiple times if task is already executing if (searchTask != null && !searchTask.isFinished()) { if (searchEvent != null) { Log_OC.d(TAG, "OCFileListSearchAsyncTask already running skipping new api call for search event: " + searchEvent.getSearchType()); @@ -1948,9 +1948,9 @@ protected void handleSearchEvent(SearchEvent event) { final User currentUser = accountManager.getUser(); - final RemoteOperation remoteOperation = getSearchRemoteOperation(currentUser, event); + final var remoteOperation = getSearchRemoteOperation(currentUser, event); - searchTask = new OCFileListSearchTask(mContainerActivity, this, remoteOperation, currentUser, event); + searchTask = new OCFileListSearchTask(mContainerActivity, this, remoteOperation, currentUser, event, SharedListFragment.TASK_TIMEOUT); searchTask.execute(); } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt index c6cbbd6f3793..dc42a9977c9d 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -20,6 +20,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import kotlinx.coroutines.withTimeoutOrNull import java.lang.ref.WeakReference @SuppressLint("NotifyDataSetChanged") @@ -28,7 +29,8 @@ class OCFileListSearchTask( fragment: OCFileListFragment, private val remoteOperation: RemoteOperation>, private val currentUser: User, - private val event: SearchEvent + private val event: SearchEvent, + private val taskTimeout: Long ) { private val activityReference: WeakReference = WeakReference(containerActivity) private val fragmentReference: WeakReference = WeakReference(fragment) @@ -48,34 +50,36 @@ class OCFileListSearchTask( fragment.setEmptyListMessage(EmptyListState.LOADING) } - val result = if (!isActive) { - false - } else { - fragment.setTitle() - lateinit var remoteOperationResult: RemoteOperationResult> - try { - remoteOperationResult = remoteOperation.execute(currentUser, fragment.requireContext()) - } catch (_: Exception) { - remoteOperationResult = - remoteOperation.executeNextcloudClient(currentUser, fragment.requireContext()) - } + val result = withTimeoutOrNull(taskTimeout) { + if (!isActive) { + false + } else { + fragment.setTitle() + lateinit var remoteOperationResult: RemoteOperationResult> + try { + remoteOperationResult = remoteOperation.execute(currentUser, fragment.requireContext()) + } catch (_: Exception) { + remoteOperationResult = + remoteOperation.executeNextcloudClient(currentUser, fragment.requireContext()) + } - if (remoteOperationResult.hasSuccessfulResult() && isActive && fragment.searchFragment) { - fragment.searchEvent = event - if (remoteOperationResult.resultData.isNullOrEmpty()) { - fragment.setEmptyView(event) - } else { - fragment.adapter.setData( - remoteOperationResult.resultData, - fragment.currentSearchType, - fileDataStorageManager, - fragment.mFile, - true - ) + if (remoteOperationResult.hasSuccessfulResult() && isActive && fragment.searchFragment) { + fragment.searchEvent = event + if (remoteOperationResult.resultData.isNullOrEmpty()) { + fragment.setEmptyView(event) + } else { + fragment.adapter.setData( + remoteOperationResult.resultData, + fragment.currentSearchType, + fileDataStorageManager, + fragment.mFile, + true + ) + } } + remoteOperationResult.isSuccess } - remoteOperationResult.isSuccess - } + } ?: false withContext(Dispatchers.Main) { if (result && isActive) { diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt b/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt index 1e59e3fac201..c146a574450c 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/SharedListFragment.kt @@ -69,7 +69,7 @@ class SharedListFragment : } override fun getSearchRemoteOperation(currentUser: User?, event: SearchEvent?): RemoteOperation<*> = - GetSharesRemoteOperation(false, SessionTimeOut(60000, 60000)) + GetSharesRemoteOperation(false, SessionTimeOut(TASK_TIMEOUT, TASK_TIMEOUT)) @Suppress("DEPRECATION") private suspend fun fetchFileData(partialFile: OCFile): OCFile? = withContext(Dispatchers.IO) { @@ -186,5 +186,6 @@ class SharedListFragment : companion object { private val SHARED_TAG = SharedListFragment::class.java.simpleName + const val TASK_TIMEOUT = 120_000 } } From ff3df751f23ed152bab3e6559ae7c461965a06af Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 16:32:59 +0200 Subject: [PATCH 4/9] add: task timeout Signed-off-by: alperozturk --- .../com/owncloud/android/ui/fragment/OCFileListFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index d73729df5b64..1e0057717a4f 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -1917,7 +1917,7 @@ protected void handleSearchEvent(SearchEvent event) { // avoid calling api multiple times if task is already executing if (searchTask != null && !searchTask.isFinished()) { if (searchEvent != null) { - Log_OC.d(TAG, "OCFileListSearchAsyncTask already running skipping new api call for search event: " + searchEvent.getSearchType()); + Log_OC.d(TAG, "OCFileListSearchTask already running skipping new api call for search event: " + searchEvent.getSearchType()); } return; From 0de55264e69fbce946cb245d92322e8fdb5b0acd Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 16:51:34 +0200 Subject: [PATCH 5/9] fix: showFederatedShareAvatar Signed-off-by: alperozturk --- .../owncloud/android/ui/AvatarGroupLayout.kt | 38 ++++++++++--------- .../ui/fragment/OCFileListSearchTask.kt | 6 +-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/AvatarGroupLayout.kt b/app/src/main/java/com/owncloud/android/ui/AvatarGroupLayout.kt index 91367c729408..ab22b2c314fd 100644 --- a/app/src/main/java/com/owncloud/android/ui/AvatarGroupLayout.kt +++ b/app/src/main/java/com/owncloud/android/ui/AvatarGroupLayout.kt @@ -138,30 +138,34 @@ class AvatarGroupLayout @JvmOverloads constructor( avatar: ImageView, viewThemeUtils: ViewThemeUtils ) { - // maybe federated share - val split = user.split("@".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - val userId: String? = split[0] - val server = split[1] - - val url = "https://" + server + "/index.php/avatar/" + userId + "/" + - resources.getInteger(R.integer.file_avatar_px) - var placeholder: Drawable? - try { - placeholder = TextDrawable.createAvatarByUserId(userId, avatarRadius) + val split = user.split("@") + val userId = split.getOrNull(0) ?: user + val server = split.getOrNull(1) + + val url = if (server != null) { + "https://$server/index.php/avatar/$userId/${resources.getInteger(R.integer.file_avatar_px)}" + } else { + // fallback: no federated server, maybe use local avatar + null + } + + val placeholder: Drawable = try { + TextDrawable.createAvatarByUserId(userId, avatarRadius) } catch (e: Exception) { Log_OC.e(TAG, "Error calculating RGB value for active account icon.", e) - placeholder = viewThemeUtils.platform.colorDrawable( - ResourcesCompat.getDrawable( - resources, - R.drawable.account_circle_white, - null - )!!, + viewThemeUtils.platform.colorDrawable( + ResourcesCompat + .getDrawable(resources, R.drawable.account_circle_white, null)!!, ContextCompat.getColor(context, R.color.black) ) } avatar.tag = null - loadCircularBitmapIntoImageView(context, url, avatar, placeholder) + if (url != null) { + loadCircularBitmapIntoImageView(context, url, avatar, placeholder) + } else { + avatar.setImageDrawable(placeholder) + } } override fun avatarGenerated(avatarDrawable: Drawable?, callContext: Any) { diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt index dc42a9977c9d..e652b174df29 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -23,7 +23,7 @@ import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeoutOrNull import java.lang.ref.WeakReference -@SuppressLint("NotifyDataSetChanged") +@SuppressLint("NotifyDataSetChanged", "LongParameterList") class OCFileListSearchTask( containerActivity: FileFragment.ContainerActivity, fragment: OCFileListFragment, @@ -46,10 +46,6 @@ class OCFileListSearchTask( fun execute() { fragmentReference.get()?.let { fragment -> job = fragment.lifecycleScope.launch(Dispatchers.IO) { - withContext(Dispatchers.Main) { - fragment.setEmptyListMessage(EmptyListState.LOADING) - } - val result = withTimeoutOrNull(taskTimeout) { if (!isActive) { false From daa5dfeb8f86ea3083f36d34f0074f858bb0af58 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 16:58:47 +0200 Subject: [PATCH 6/9] fix: codacy Signed-off-by: alperozturk --- .../com/owncloud/android/ui/fragment/OCFileListSearchTask.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt index e652b174df29..5aa41ffeb8f7 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -23,7 +23,8 @@ import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeoutOrNull import java.lang.ref.WeakReference -@SuppressLint("NotifyDataSetChanged", "LongParameterList") +@Suppress("LongParameterList") +@SuppressLint("NotifyDataSetChanged") class OCFileListSearchTask( containerActivity: FileFragment.ContainerActivity, fragment: OCFileListFragment, From aaba52d3f6f042d2c0cc172e35a8d25f7325dc96 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 16 Oct 2025 14:35:32 +0200 Subject: [PATCH 7/9] add: new no internet icon Signed-off-by: alperozturk --- .../android/ui/fragment/ExtendedListFragment.kt | 2 +- app/src/main/res/drawable/ic_no_internet.xml | 17 +++++++++++++++++ gradle/verification-metadata.xml | 8 ++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/drawable/ic_no_internet.xml diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt b/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt index cb56d08733ad..f1fb8123758c 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.kt @@ -711,7 +711,7 @@ open class ExtendedListFragment : setMessageForEmptyList( R.string.file_list_error_headline, R.string.file_list_error_description, - R.drawable.ic_synchronizing_error, + R.drawable.ic_no_internet, false ) } diff --git a/app/src/main/res/drawable/ic_no_internet.xml b/app/src/main/res/drawable/ic_no_internet.xml new file mode 100644 index 000000000000..623ec3333316 --- /dev/null +++ b/app/src/main/res/drawable/ic_no_internet.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index bdf244ca136e..6c0aefbb33dc 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -16243,6 +16243,14 @@ + + + + + + + + From f2ad2650af712cc22e68c3b151346f1cf67d66c6 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 3 Nov 2025 09:13:37 +0100 Subject: [PATCH 8/9] fix git conflict Signed-off-by: alperozturk [skip ci] --- app/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9b73dee8a44c..3054b95c35cf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,8 +10,8 @@ Favorites Assistant Media - - + Poor connection + Check your internet connection or try again later %1$s Android app version %1$s version %1$s, build #%2$s From 7f29183f729c7622eb8cbf8439d26f5029cfd704 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 13 Nov 2025 09:18:05 +0100 Subject: [PATCH 9/9] fix: build Signed-off-by: alperozturk --- app/build.gradle | 2 +- appscan/build.gradle | 2 +- build.gradle | 2 +- gradle/verification-metadata.xml | 29 +++++++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 4a8122c6dca8..c47925cf6634 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -116,7 +116,7 @@ android { applicationId = "com.nextcloud.client" minSdk = 27 targetSdk = 35 - compileSdk = 35 + compileSdk = 36 buildConfigField "boolean", "CI", ciBuild.toString() buildConfigField "boolean", "RUNTIME_PERF_ANALYSIS", perfAnalysis.toString() diff --git a/appscan/build.gradle b/appscan/build.gradle index 2dd65e4eabb9..c5ec454de7ef 100644 --- a/appscan/build.gradle +++ b/appscan/build.gradle @@ -23,7 +23,7 @@ android { defaultConfig { minSdk = 27 targetSdk = 35 - compileSdk = 35 + compileSdk = 36 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/build.gradle b/build.gradle index a339599da8b9..9eb381094ea7 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ */ buildscript { ext { - androidLibraryVersion = "8c77f600ac942f6eb4e3c4447143fc949d34acc6" + androidLibraryVersion = "2.22.1" androidCommonLibraryVersion = "0.28.0" androidPluginVersion = '8.13.0' androidxMediaVersion = "1.5.1" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 6c0aefbb33dc..1856a5d3540d 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -11,6 +11,9 @@ + + + @@ -3401,6 +3404,11 @@ + + + + + @@ -15971,6 +15979,14 @@ + + + + + + + + @@ -19820,6 +19836,11 @@ + + + + + @@ -19905,6 +19926,14 @@ + + + + + + + +