Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
0db3789
feat(unified-share): ui
alperozturk96 Apr 16, 2026
817e702
feat(unified-share): ui
alperozturk96 Apr 16, 2026
9638ccc
add todos
alperozturk96 Apr 17, 2026
040f5e9
add todos
alperozturk96 Apr 17, 2026
9e52437
add todos
alperozturk96 Apr 17, 2026
40a915a
wip
alperozturk96 Apr 17, 2026
a5216e0
wip
alperozturk96 Apr 17, 2026
4cf8753
wip
alperozturk96 Apr 17, 2026
aeb4882
wip
alperozturk96 Apr 17, 2026
a82d095
wip
alperozturk96 May 5, 2026
d8b7143
wip
alperozturk96 May 5, 2026
074292f
wip
alperozturk96 May 6, 2026
e1f443d
wip
alperozturk96 Jun 9, 2026
57b5ce4
use getMaxCompatibleE2EEVersion
alperozturk96 Jun 12, 2026
597772b
wip
alperozturk96 Jun 17, 2026
f9dd681
wip
alperozturk96 Jul 2, 2026
0cb8efe
wip
alperozturk96 Jul 2, 2026
3857565
wip
alperozturk96 Jul 3, 2026
bfda050
wip
alperozturk96 Jul 6, 2026
ca3c1cc
wip
alperozturk96 Jul 6, 2026
1cac0da
wip
alperozturk96 Jul 8, 2026
d7a42d1
wip
alperozturk96 Jul 9, 2026
44a377e
wip
alperozturk96 Jul 14, 2026
d440414
wip
alperozturk96 Jul 14, 2026
6b65236
wip
alperozturk96 Jul 22, 2026
278221e
wip
alperozturk96 Jul 29, 2026
c811a95
wip
alperozturk96 Jul 29, 2026
7f98a93
wip
alperozturk96 Aug 10, 2026
f78d71b
wip
alperozturk96 Aug 10, 2026
1247e37
wip
alperozturk96 Aug 10, 2026
74476ea
wip
alperozturk96 Aug 20, 2026
5137256
wip
alperozturk96 Aug 21, 2026
9085305
wip
alperozturk96 Aug 21, 2026
3b46ffe
wip
alperozturk96 Sep 1, 2026
229d212
wip
alperozturk96 Sep 3, 2026
20ac045
wip
alperozturk96 Sep 3, 2026
5c1fe4b
wip
alperozturk96 Sep 3, 2026
4a28e03
wip
alperozturk96 Sep 3, 2026
78932bb
wip
alperozturk96 Sep 3, 2026
1ba0a2f
wip
alperozturk96 Sep 4, 2026
4529148
wip
alperozturk96 Sep 4, 2026
ed3e16d
wip
alperozturk96 Sep 4, 2026
522e42d
wip
alperozturk96 Sep 4, 2026
b286341
wip
alperozturk96 Sep 4, 2026
f17bdd7
wip
alperozturk96 Sep 8, 2026
e0545c7
wip
alperozturk96 Sep 8, 2026
7b68a75
wip
alperozturk96 Sep 8, 2026
19a15e1
wip
alperozturk96 Sep 8, 2026
93d7a6a
wip
alperozturk96 Sep 8, 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 @@ -2373,6 +2373,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 @@ -2576,6 +2578,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 @@ -612,9 +612,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