Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
248e1c4
feat(unified-share): ui
alperozturk96 Apr 16, 2026
73772f4
feat(unified-share): ui
alperozturk96 Apr 16, 2026
8338cde
add todos
alperozturk96 Apr 17, 2026
cc4f870
add todos
alperozturk96 Apr 17, 2026
ec997d3
add todos
alperozturk96 Apr 17, 2026
e6ffe47
wip
alperozturk96 Apr 17, 2026
a9a8af5
wip
alperozturk96 Apr 17, 2026
5a61887
wip
alperozturk96 Apr 17, 2026
166c82d
wip
alperozturk96 Apr 17, 2026
441ed34
wip
alperozturk96 May 5, 2026
0c3fd76
wip
alperozturk96 May 5, 2026
936be37
wip
alperozturk96 May 6, 2026
3904891
wip
alperozturk96 Jun 9, 2026
7c0da4d
use getMaxCompatibleE2EEVersion
alperozturk96 Jun 12, 2026
858b70c
wip
alperozturk96 Jun 17, 2026
ea0da2d
wip
alperozturk96 Jul 2, 2026
2072ca2
wip
alperozturk96 Jul 2, 2026
24abf09
wip
alperozturk96 Jul 3, 2026
45673c0
wip
alperozturk96 Jul 6, 2026
a40810c
wip
alperozturk96 Jul 6, 2026
8b47f43
wip
alperozturk96 Jul 8, 2026
0df88c8
wip
alperozturk96 Jul 9, 2026
ae7f65e
wip
alperozturk96 Jul 14, 2026
424e41b
wip
alperozturk96 Jul 14, 2026
8adf8b3
wip
alperozturk96 Jul 22, 2026
d1bc1f2
wip
alperozturk96 Jul 29, 2026
fc8375a
wip
alperozturk96 Jul 29, 2026
9fe07f7
wip
alperozturk96 Aug 10, 2026
1165195
wip
alperozturk96 Aug 10, 2026
6b3ab13
wip
alperozturk96 Aug 10, 2026
5e4c6c5
wip
alperozturk96 Aug 20, 2026
8de7b88
wip
alperozturk96 Aug 21, 2026
1ed1433
wip
alperozturk96 Aug 21, 2026
474f28e
wip
alperozturk96 Sep 1, 2026
7612c52
wip
alperozturk96 Sep 3, 2026
8d7f457
wip
alperozturk96 Sep 3, 2026
5a192d7
wip
alperozturk96 Sep 3, 2026
d157d85
wip
alperozturk96 Sep 3, 2026
6f45ded
wip
alperozturk96 Sep 3, 2026
5b9c744
wip
alperozturk96 Sep 4, 2026
639e7bd
wip
alperozturk96 Sep 4, 2026
2ab0e55
wip
alperozturk96 Sep 4, 2026
bdbacb9
wip
alperozturk96 Sep 4, 2026
30c4ce6
wip
alperozturk96 Sep 4, 2026
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
1,333 changes: 1,333 additions & 0 deletions app/schemas/com.nextcloud.client.database.NextcloudDatabase/105.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ import com.owncloud.android.db.ProviderMeta
AutoMigration(from = 100, to = 101, spec = DatabaseMigrationUtil.ResetCapabilitiesPostMigration::class),
AutoMigration(from = 101, to = 102, spec = DatabaseMigrationUtil.ResetCapabilitiesPostMigration::class),
AutoMigration(from = 102, to = 103, spec = DatabaseMigrationUtil.ResetCapabilitiesPostMigration::class),
AutoMigration(from = 103, to = 104)
AutoMigration(from = 103, to = 104),
AutoMigration(from = 104, to = 105, spec = DatabaseMigrationUtil.ResetCapabilitiesPostMigration::class)
],
exportSchema = true
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ data class CapabilityEntity(
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_MOD_REWRITE_WORKING)
val modRewriteWorking: Int?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_CHUNKED_UPLOAD_MAX_SIZE)
val chunkedUploadMaxSize: Long?
val chunkedUploadMaxSize: Long?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SHARING_JSON)
val sharingJson: String?
)

@Suppress("LongMethod", "ReturnCount")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package com.nextcloud.utils.extensions

import android.content.Context
import com.nextcloud.android.common.ui.network.auth.ServerCredentials
import com.nextcloud.common.NextcloudClient
import com.owncloud.android.lib.common.OwnCloudClient
import com.owncloud.android.lib.common.OwnCloudClientFactory
Expand All @@ -34,3 +35,9 @@ fun OwnCloudClient.getVideoPreviewEndpoint(localFileId: Long, size: Int): String
localFileId +
"&x=" + size + "&y=" + size +
"&a=1&forceIcon=0"

/**
* Used in Android Common
*/
fun OwnCloudClient.toServerCredentials(baseURL: String): ServerCredentials =
ServerCredentials(baseURL, userIdPlain, credentials.authToken)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.utils.extensions

import com.nextcloud.android.common.ui.network.auth.ServerCredentials
import com.nextcloud.android.common.ui.network.http.NextcloudHttpClient
import com.nextcloud.android.common.ui.network.model.dataOrElse
import com.nextcloud.android.common.ui.share.repository.ShareRemoteRepository
import com.owncloud.android.lib.common.utils.Log_OC

private const val TAG = "ServerCredentialsExtensions"

suspend fun ServerCredentials.supportsUnifiedShare(): Boolean {
val capabilities = ShareRemoteRepository(NextcloudHttpClient.create(this))
.fetchSharingCapabilities()
.dataOrElse { Log_OC.e(TAG, "Failed to fetch sharing capabilities") }

return capabilities?.isUnifiedShareEnabled == true
}
27 changes: 27 additions & 0 deletions app/src/main/java/com/nextcloud/utils/extensions/UserExtensions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.utils.extensions

import com.nextcloud.android.common.ui.network.auth.ServerCredentials
import com.nextcloud.client.account.User
import com.owncloud.android.MainApp
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
import com.owncloud.android.lib.common.utils.Log_OC

private const val TAG = "UserExtensions"

@Suppress("TooGenericExceptionCaught")
fun User.toServerCredentials(): ServerCredentials? = try {
OwnCloudClientManagerFactory
.getDefaultSingleton()
.getClientFor(toOwnCloudAccount(), MainApp.getAppContext())
.toServerCredentials(server.uri.toString())
} catch (e: Exception) {
Log_OC.e(TAG, "Failed to create client for $accountName", e)
null
}
Original file line number Diff line number Diff line change
Expand Up @@ -2446,6 +2446,8 @@ private ContentValues createContentValues(String accountName, OCCapability capab

contentValues.put(ProviderTableMeta.CAPABILITIES_CHUNKED_UPLOAD_MAX_SIZE, capability.getChunkedUploadMaxSize());

contentValues.put(ProviderTableMeta.CAPABILITIES_SHARING_JSON, capability.getSharingJson());

return contentValues;
}

Expand Down Expand Up @@ -2649,6 +2651,8 @@ private OCCapability createCapabilityInstance(Cursor cursor) {

capability.setChunkedUploadMaxSize(
getLong(cursor, ProviderTableMeta.CAPABILITIES_CHUNKED_UPLOAD_MAX_SIZE));

capability.setSharingJson(getString(cursor, ProviderTableMeta.CAPABILITIES_SHARING_JSON));
}

return capability;
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/com/owncloud/android/db/ProviderMeta.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*/
public class ProviderMeta {
public static final String DB_NAME = "filelist";
public static final int DB_VERSION = 104;
public static final int DB_VERSION = 105;

private ProviderMeta() {
// No instance
Expand Down Expand Up @@ -299,6 +299,7 @@ static public class ProviderTableMeta implements BaseColumns {
public static final String CAPABILITIES_CLIENT_INTEGRATION_JSON = "client_integration_json";
public static final String CAPABILITIES_MOD_REWRITE_WORKING = "mod_rewrite_working";
public static final String CAPABILITIES_CHUNKED_UPLOAD_MAX_SIZE = "chunked_upload_max_size";
public static final String CAPABILITIES_SHARING_JSON = "sharing_json";

//Columns of Uploads table
public static final String UPLOADS_LOCAL_PATH = "local_path";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -608,9 +608,12 @@ private void bindSharedAvatars(ListItemViewHolder holder, OCFile file) {
if (sharedAvatars.getChildCount() > 0) {
sharedAvatars.removeAllViews();
}
final var avatars = helper.getAvatarSharees(file, userId);
sharedAvatars.setAvatars(user, avatars, viewThemeUtils);
sharedAvatars.setOnClickListener(view -> ocFileListFragmentInterface.onShareIconClick(file));

helper.getAvatarSharees(file, user, userId, avatars -> {
sharedAvatars.setAvatars(user, avatars, viewThemeUtils);
sharedAvatars.setOnClickListener(view -> ocFileListFragmentInterface.onShareIconClick(file));
return Unit.INSTANCE;
});
}

private void bindListItemViewHolder(ListItemViewHolder holder, OCFile file) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@

package com.owncloud.android.ui.adapter.helper

import com.nextcloud.android.common.ui.share.avatar.ShareAvatarRepository
import com.nextcloud.android.common.ui.share.model.api.share.Share
import com.nextcloud.client.account.User
import com.nextcloud.client.database.entity.FileEntity
import com.nextcloud.client.preferences.AppPreferences
import com.nextcloud.utils.extensions.filterFilenames
import com.nextcloud.utils.extensions.isTempFile
import com.nextcloud.utils.extensions.supportsUnifiedShare
import com.nextcloud.utils.extensions.toServerCredentials
import com.owncloud.android.MainApp
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.resources.shares.ShareType
Expand Down Expand Up @@ -56,19 +61,36 @@ class OCFileListAdapterHelper {
}
}

fun getAvatarSharees(file: OCFile, userId: String?): List<ShareeUser> {
val sharees = file.sharees
val ownerId = file.ownerId
fun getAvatarSharees(file: OCFile, user: User?, userId: String?, onComplete: (List<ShareeUser>) -> Unit) {
scope.launch {
val credentials = user?.toServerCredentials()
val result = if (credentials != null && credentials.supportsUnifiedShare()) {
ShareAvatarRepository(credentials).fetchShareAvatars(file.remoteId)?.toAvatarSharees().orEmpty()
} else {
file.toLocalSharees(userId)
}

val ownerSharee = if (!ownerId.isNullOrEmpty() && ownerId != userId) {
ShareeUser(ownerId, file.ownerDisplayName, ShareType.USER).takeIf { it !in sharees }
} else {
null
withContext(Dispatchers.Main) {
onComplete(result)
}
}
}

private fun OCFile.toLocalSharees(userId: String?): List<ShareeUser> {
val ownerSharee = ownerId
?.takeIf { it.isNotEmpty() && it != userId }
?.let { ShareeUser(it, ownerDisplayName, ShareType.USER) }
?.takeIf { it !in sharees }

return listOfNotNull(ownerSharee) + sharees.asReversed()
}

private fun List<Share>.toAvatarSharees(): List<ShareeUser> = asSequence()
.flatMap { share -> share.invitedRecipients }
.distinctBy { recipient -> recipient.value }
.map { recipient -> ShareeUser(recipient.value, recipient.displayName, ShareType.USER) }
.toList()

suspend fun prepareFileList(
directory: OCFile,
dataProvider: OCFileListAdapterDataProvider,
Expand Down
Loading
Loading