From 4c80d1c5c3c9d5b28c90073a76d2bc53b4854b03 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 15:46:04 +0200 Subject: [PATCH 1/8] 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 +- gradle/verification-metadata.xml | 8 ++ 5 files changed, 108 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 e89e9ccad935..43fde00bd0ba 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; @@ -350,8 +350,8 @@ public void onDetach() { setOnRefreshListener(null); mContainerActivity = null; - if (remoteOperationAsyncTask != null) { - remoteOperationAsyncTask.cancel(true); + if (searchTask != null) { + searchTask.cancel(); } super.onDetach(); } @@ -1908,7 +1908,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()); } @@ -1943,9 +1943,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) { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7f7c63031fe9..472a5eba25e2 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -17655,6 +17655,14 @@ + + + + + + + + From 0f7ce1e33fb159a97b4cf5f1c28963775d007aef Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 15:49:22 +0200 Subject: [PATCH 2/8] 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 92aa26e12b74..328e6a4bf783 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 @@ -704,6 +704,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 d9d0f88bce97c09052c09a50367c7cda8955bf2e Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 16:32:23 +0200 Subject: [PATCH 3/8] 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 328e6a4bf783..725db2b7943a 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 @@ -709,7 +709,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 43fde00bd0ba..30102cf84069 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 @@ -1907,7 +1907,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()); @@ -1941,9 +1941,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 0dbaf81dbbbc4256ac3284b95f4888bf98e1dc90 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 16:32:59 +0200 Subject: [PATCH 4/8] 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 30102cf84069..2489b4d555d0 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 @@ -1910,7 +1910,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 3a8bbd0ebbb978b5d9c2f3564e12b3b5f94376f7 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 16:51:34 +0200 Subject: [PATCH 5/8] 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 9be50ef1427d4fc606d252b6190fdcefca92f48a Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Oct 2025 16:58:47 +0200 Subject: [PATCH 6/8] 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 dff8ee60a3f083eceecfa87553a0d0244d766f83 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Thu, 16 Oct 2025 14:35:32 +0200 Subject: [PATCH 7/8] 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 725db2b7943a..9c49e9df88a3 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 @@ -708,7 +708,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 472a5eba25e2..97f678fdb93e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -17735,6 +17735,14 @@ + + + + + + + + From d31db26d00c3dd2adce6451849f07eeda5af3d69 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Mon, 3 Nov 2025 09:13:37 +0100 Subject: [PATCH 8/8] fix git conflict Signed-off-by: alperozturk --- app/src/main/res/values/strings.xml | 4 ++-- gradle/libs.versions.toml | 2 +- gradle/verification-metadata.xml | 8 ++++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index af071a6e9d29..18755e00ceae 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 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index db1af805091f..6ca9c2b760ea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ androidCommonLibraryVersion = "0.29.0" androidGifDrawableVersion = "1.2.29" androidImageCropperVersion = "4.6.0" -androidLibraryVersion = "3546bd82fc" +androidLibraryVersion = "8c77f600ac942f6eb4e3c4447143fc949d34acc6" androidPluginVersion = '8.13.0' androidsvgVersion = "1.4" androidxMediaVersion = "1.5.1" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 97f678fdb93e..18fa2a4cd802 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -17839,6 +17839,14 @@ + + + + + + + +