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 @@ -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_no_internet,
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 @@ -350,8 +350,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 @@ -1902,10 +1902,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 @@ -1936,11 +1936,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 <[email protected]>
* SPDX-FileCopyrightText: 2022 Álvaro Brey <[email protected]>
* 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
}
}
17 changes: 17 additions & 0 deletions app/src/main/res/drawable/ic_no_internet.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!--
~ SPDX-FileCopyrightText: 2025 Alper Ozturk <[email protected]>
~ SPDX-FileCopyrightText: 2018-2025 Google LLC
~ SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#626364"
android:viewportWidth="960"
android:viewportHeight="960">

<path
android:fillColor="@android:color/white"
android:pathData="M73,424L2,353Q99,259 222.5,209.5Q346,160 480,160Q614,160 737.5,209.5Q861,259 958,353L887,424Q805,345 700,302.5Q595,260 480,260Q365,260 260,302.5Q155,345 73,424ZM480,800Q447,800 423.5,776.5Q400,753 400,720Q400,687 423.5,663.5Q447,640 480,640Q513,640 536.5,663.5Q560,687 560,720Q560,753 536.5,776.5Q513,800 480,800ZM298,651L228,580Q279,532 344,506Q409,480 480,480Q521,480 560.5,488.5Q600,497 636,514Q619,531 603,552.5Q587,574 574,597Q551,589 527.5,584.5Q504,580 480,580Q429,580 382.5,598Q336,616 298,651ZM186,538L116,467Q190,396 284,358Q378,320 481,320Q584,320 677.5,357.5Q771,395 845,466L830,482Q810,479 793.5,474.5Q777,470 760,470Q746,470 731.5,473.5Q717,477 701,482Q651,452 595,436Q539,420 480,420Q397,420 321.5,450.5Q246,481 186,538ZM760,800Q743,800 731.5,788.5Q720,777 720,760Q720,743 731.5,731.5Q743,720 760,720Q777,720 788.5,731.5Q800,743 800,760Q800,777 788.5,788.5Q777,800 760,800ZM720,680L720,540L800,540L800,680L720,680Z" />

</vector>
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 @@ -1454,4 +1454,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">Poor connection</string>
<string name="file_list_error_description">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 ="3546bd82fc"
androidLibraryVersion ="72d739551d"
androidCommonLibraryVersion = "0.28.0"
androidPluginVersion = '8.13.0'
androidxMediaVersion = "1.5.1"
Expand Down
16 changes: 16 additions & 0 deletions gradle/verification-metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16198,6 +16198,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 Expand Up @@ -16270,6 +16278,14 @@
<sha256 value="0e72841878595f83c6d8f93aa51f78a67e821f53446fcb7a5d94cfaad8ebbbac" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
</component>
<component group="com.github.nextcloud" name="android-library" version="72d739551d">
<artifact name="android-library-72d739551d.aar">
<sha256 value="587886bac4903337dbbb379ba2b3452066427241d97150423a3b966418b9dd91" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
<artifact name="android-library-72d739551d.module">
<sha256 value="6540bd9ced6fc12bf9255ba87b2890bb07d06c0a4f9b97a8a086a15c24c62a90" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
</component>
<component group="com.github.nextcloud" name="android-library" version="7444d0e832bb35b708c2d84878d9727d24289385">
<artifact name="android-library-7444d0e832bb35b708c2d84878d9727d24289385.aar">
<sha256 value="c253a126ca3c32dd5b373ab1c64668e4603305b3113b052fc0fc5e3c833a913c" origin="Generated by Gradle" reason="Artifact is not signed"/>
Expand Down
Loading