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
38 changes: 21 additions & 17 deletions app/src/main/java/com/owncloud/android/ui/AvatarGroupLayout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
false
)
}
else -> {
setMessageForEmptyList(
R.string.file_list_empty_headline,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
protected SearchType currentSearchType;
protected boolean searchFragment;
protected SearchEvent searchEvent;
protected AsyncTask<Void, Void, Boolean> remoteOperationAsyncTask;
private OCFileListSearchTask searchTask;
protected String mLimitToMimeType;
private FloatingActionButton mFabMain;
public static boolean isMultipleFileSelectedForCopyOrMove = false;
Expand Down Expand Up @@ -356,8 +356,8 @@ public void onDetach() {
setOnRefreshListener(null);
mContainerActivity = null;

if (remoteOperationAsyncTask != null) {
remoteOperationAsyncTask.cancel(true);
if (searchTask != null) {
searchTask.cancel();
}
super.onDetach();
}
Expand Down Expand Up @@ -1908,10 +1908,10 @@ protected void handleSearchEvent(SearchEvent event) {
return;
}

// avoid calling api multiple times if async task is already executing
if (remoteOperationAsyncTask != null && remoteOperationAsyncTask.getStatus() != AsyncTask.Status.FINISHED) {
// 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;
Expand Down Expand Up @@ -1942,11 +1942,10 @@ protected void handleSearchEvent(SearchEvent event) {

final User currentUser = accountManager.getUser();

final RemoteOperation remoteOperation = getSearchRemoteOperation(currentUser, event);
final var 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, SharedListFragment.TASK_TIMEOUT);
searchTask.execute();
}


Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2022 Álvaro Brey <alvaro@alvarobrey.com>
* 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 kotlinx.coroutines.withTimeoutOrNull
import java.lang.ref.WeakReference

@Suppress("LongParameterList")
@SuppressLint("NotifyDataSetChanged")
class OCFileListSearchTask(
containerActivity: FileFragment.ContainerActivity,
fragment: OCFileListFragment,
private val remoteOperation: RemoteOperation<List<Any>>,
private val currentUser: User,
private val event: SearchEvent,
private val taskTimeout: Long
) {
private val activityReference: WeakReference<FileFragment.ContainerActivity> = WeakReference(containerActivity)
private val fragmentReference: WeakReference<OCFileListFragment> = WeakReference(fragment)

private val fileDataStorageManager: FileDataStorageManager?
get() = activityReference.get()?.storageManager

private fun RemoteOperationResult<out Any>.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) {
val result = withTimeoutOrNull(taskTimeout) {
if (!isActive) {
false
} else {
fragment.setTitle()
lateinit var remoteOperationResult: RemoteOperationResult<List<Any>>
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
}
} ?: false

withContext(Dispatchers.Main) {
if (result && isActive) {
fragment.adapter.notifyDataSetChanged()
} else {
fragment.setEmptyListMessage(EmptyListState.ERROR)
}
}
}
}
}

fun cancel() = job?.cancel(null)

fun isFinished(): Boolean = job?.isCompleted == true
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -68,7 +69,7 @@ class SharedListFragment :
}

override fun getSearchRemoteOperation(currentUser: User?, event: SearchEvent?): RemoteOperation<*> =
GetSharesRemoteOperation()
GetSharesRemoteOperation(false, SessionTimeOut(TASK_TIMEOUT, TASK_TIMEOUT))

@Suppress("DEPRECATION")
private suspend fun fetchFileData(partialFile: OCFile): OCFile? = withContext(Dispatchers.IO) {
Expand Down Expand Up @@ -185,5 +186,6 @@ class SharedListFragment :

companion object {
private val SHARED_TAG = SharedListFragment::class.java.simpleName
const val TASK_TIMEOUT = 120_000
}
}
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1440,4 +1440,7 @@
<string name="clear">Clear</string>
<string name="set_message">Set message</string>
<string name="error_setting_status_message">Error setting status message!</string>

<string name="file_list_error_headline">Oops!</string>
<string name="file_list_error_description">We couldn’t fetch your files. Please check your internet connection or try again later.</string>
</resources>
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/
buildscript {
ext {
androidLibraryVersion ="5da34c70da4068ff976cf931b7716fc7a337f32d"
androidLibraryVersion ="55ed1b1b63"
androidCommonLibraryVersion = "0.28.0"
androidPluginVersion = '8.13.0'
androidxMediaVersion = "1.5.1"
Expand Down
8 changes: 8 additions & 0 deletions gradle/verification-metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16182,6 +16182,14 @@
<sha256 value="36dfd05a9d3b9df4db8aceeb6cbefa31ffde4f7199a7765e841042ec022c0c60" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
</component>
<component group="com.github.nextcloud" name="android-library" version="55ed1b1b63">
<artifact name="android-library-55ed1b1b63.aar">
<sha256 value="bca903c58a485d53b88b0b5f8a5201e0ac11d7630b8fbef4829d68131eeddc0f" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
<artifact name="android-library-55ed1b1b63.module">
<sha256 value="b6d96caf23a995c1d15dddb349cc056c7544eeead69404212e02119dcc7c6ba9" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
</component>
<component group="com.github.nextcloud" name="android-library" version="5da34c70da4068ff976cf931b7716fc7a337f32d">
<artifact name="android-library-5da34c70da4068ff976cf931b7716fc7a337f32d.aar">
<sha256 value="22c05e04d2b2667c39da419b2d3d07e7832babd4b2e235aa5d4394a4fecf92ee" origin="Generated by Gradle" reason="Artifact is not signed"/>
Expand Down
Loading