From be08922d91dba36f9d3fcac1d176eab712f5a572 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Tue, 27 Oct 2026 15:25:08 +0300 Subject: [PATCH 1/2] fix(account-name): handling --- app/build.gradle.kts | 4 +- .../ChooseAccountDialogCompose.kt | 16 ++-- .../ConversationsListActivity.kt | 12 +-- .../FullScreenTextViewerActivity.kt | 15 ++-- .../com/nextcloud/talk/utils/AccountUtils.kt | 89 ++++++++++--------- .../nextcloud/talk/utils/FileViewerUtils.kt | 12 +-- gradle/verification-metadata.xml | 24 +++++ 7 files changed, 96 insertions(+), 76 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9a908818ccf..10d0dd915e1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -336,8 +336,8 @@ dependencies { implementation("androidx.core:core-splashscreen:1.2.0") implementation("androidx.sharetarget:sharetarget:1.2.0") implementation("androidx.activity:activity-ktx:1.13.0") - implementation("com.github.nextcloud.android-common:ui:0.34.0") - implementation("com.github.nextcloud.android-common:core:0.34.0") + implementation("com.github.nextcloud.android-common:ui:f6515c1c36") + implementation("com.github.nextcloud.android-common:core:f6515c1c36") implementation("com.github.nextcloud-deps:android-talk-webrtc:155.8059.1") implementation("com.github.nextcloud-releases:talk-clients-vodozemac:0.0.2") diff --git a/app/src/main/java/com/nextcloud/talk/chooseaccount/ChooseAccountDialogCompose.kt b/app/src/main/java/com/nextcloud/talk/chooseaccount/ChooseAccountDialogCompose.kt index 3a0201d225e..ea281ef7ba8 100644 --- a/app/src/main/java/com/nextcloud/talk/chooseaccount/ChooseAccountDialogCompose.kt +++ b/app/src/main/java/com/nextcloud/talk/chooseaccount/ChooseAccountDialogCompose.kt @@ -95,6 +95,7 @@ import com.nextcloud.talk.ui.StatusDrawable import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.users.DefaultAccountProvider import com.nextcloud.talk.users.UserManager +import com.nextcloud.talk.utils.AccountUtils import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.CapabilitiesUtil import com.nextcloud.talk.utils.DisplayUtils @@ -213,11 +214,11 @@ class ChooseAccountDialogCompose { }, onEcosystemFilesClick = { shouldDismiss.value = true - openEcosystemFiles(currentUser) + openEcosystemFiles(activity, currentUser) }, onEcosystemNotesClick = { shouldDismiss.value = true - openEcosystemNotes(currentUser) + openEcosystemNotes(activity, currentUser) }, onEcosystemMoreClick = { shouldDismiss.value = true @@ -294,15 +295,16 @@ class ChooseAccountDialogCompose { activity.startActivity(intent) } - private fun openEcosystemFiles(currentUser: User) { - ecosystemManager.openApp(EcosystemApp.FILES, getAccountHandle(currentUser)) + private fun openEcosystemFiles(activity: Activity, currentUser: User) { + ecosystemManager.openApp(EcosystemApp.FILES, getAccountHandle(activity, currentUser)) } - private fun openEcosystemNotes(currentUser: User) { - ecosystemManager.openApp(EcosystemApp.NOTES, getAccountHandle(currentUser)) + private fun openEcosystemNotes(activity: Activity, currentUser: User) { + ecosystemManager.openApp(EcosystemApp.NOTES, getAccountHandle(activity, currentUser)) } - private fun getAccountHandle(user: User): String = user.username + "@" + user.baseUrl?.toUri()?.host + private fun getAccountHandle(activity: Activity, user: User): String? = + AccountUtils.findFilesAccountName(activity, user) ?: AccountUtils.buildAccountName(user) private fun openEcosystemMore(activity: Activity) { LinkHelper.openAppStore("Nextcloud", true, activity) diff --git a/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt index 39fa63eec93..da01d75f791 100644 --- a/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt @@ -46,6 +46,7 @@ import androidx.work.WorkInfo import androidx.work.WorkManager import autodagger.AutoInjector import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.nextcloud.android.common.core.utils.AccountNameUtils import com.nextcloud.android.common.core.utils.ecosystem.AccountReceiverCallback import com.nextcloud.android.common.core.utils.ecosystem.EcosystemManager import com.nextcloud.talk.R @@ -97,6 +98,7 @@ import com.nextcloud.talk.ui.dialog.FilterConversationFragment import com.nextcloud.talk.ui.dialog.FilterConversationFragment.Companion.ARCHIVE import com.nextcloud.talk.ui.dialog.FilterConversationFragment.Companion.MENTION import com.nextcloud.talk.ui.dialog.FilterConversationFragment.Companion.UNREAD +import com.nextcloud.talk.utils.AccountUtils import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.AppTasks import com.nextcloud.talk.utils.BrandingUtils @@ -561,22 +563,16 @@ class ConversationsListActivity : BaseActivity() { ecosystemManager.receiveAccount( intent, object : AccountReceiverCallback { - @SuppressLint("UseKtx") override fun onAccountReceived(accountName: String) { - val baseUrl = accountName.substringAfterLast("@") - val trimmedAccountName = accountName.substringBeforeLast("@") lifecycleScope.launch { - val users = userManager.getUsers() - val user = users.firstOrNull { user -> - user.username == trimmedAccountName && baseUrl == user.baseUrl?.toUri()?.host - } + val user = AccountUtils.findUserForFilesAccount(context, accountName, userManager.getUsers()) if (user != null && userManager.setUserAsActive(user)) { startActivity(createInPlaceAccountSwitchIntent(context, user.id!!)) } else { showSnackbar(getString(R.string.nc_no_account_found)) } } - Log.d(TAG, trimmedAccountName) + Log.d(TAG, AccountNameUtils.getUserPart(accountName)) } override fun onAccountError(reason: String) { diff --git a/app/src/main/java/com/nextcloud/talk/fullscreenfile/FullScreenTextViewerActivity.kt b/app/src/main/java/com/nextcloud/talk/fullscreenfile/FullScreenTextViewerActivity.kt index d4fcc1d2910..65c8984a4e0 100644 --- a/app/src/main/java/com/nextcloud/talk/fullscreenfile/FullScreenTextViewerActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/fullscreenfile/FullScreenTextViewerActivity.kt @@ -26,8 +26,9 @@ import com.nextcloud.talk.R import com.nextcloud.talk.activities.BaseActivity import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.components.ColoredStatusBar +import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.ui.dialog.SaveToStorageDialogFragment -import com.nextcloud.talk.utils.AccountUtils.canWeOpenFilesApp +import com.nextcloud.talk.utils.AccountUtils.resolveFilesAccountName import com.nextcloud.talk.utils.FileUtils import com.nextcloud.talk.utils.Mimetype.TEXT_PREFIX_GENERIC import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ACCOUNT @@ -51,8 +52,6 @@ class FullScreenTextViewerActivity : BaseActivity() { val isMarkdown = intent.getBooleanExtra("IS_MARKDOWN", false) val fileId = intent.getStringExtra("FILE_ID").orEmpty() val link = intent.getStringExtra("LINK") - val username = user.username.orEmpty() - val baseUrl = user.baseUrl.orEmpty() textFile = FileUtils.resolveSharedAttachmentFile(applicationContext.cacheDir, fileName) ?: run { Log.e(TAG, "Invalid text filename: $fileName") finish() @@ -80,7 +79,7 @@ class FullScreenTextViewerActivity : BaseActivity() { onShare = { shareFile() }, onSave = { showSaveDialog(fileName) }, onOpenInFilesApp = if (fileId.isNotEmpty()) { - { openInFilesApp(link, fileId, username, baseUrl) } + { openInFilesApp(link, fileId, user) } } else { null } @@ -90,9 +89,9 @@ class FullScreenTextViewerActivity : BaseActivity() { } } - private fun openInFilesApp(link: String?, fileId: String, username: String, baseUrl: String) { - val accountString = "$username@${baseUrl.replace("https://", "").replace("http://", "")}" - if (canWeOpenFilesApp(this, accountString)) { + private fun openInFilesApp(link: String?, fileId: String, user: User) { + val accountName = resolveFilesAccountName(this, user) + if (accountName != null) { val filesAppIntent = Intent(Intent.ACTION_VIEW, null) val componentName = ComponentName( getString(R.string.nc_import_accounts_from), @@ -101,7 +100,7 @@ class FullScreenTextViewerActivity : BaseActivity() { filesAppIntent.component = componentName filesAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) filesAppIntent.setPackage(getString(R.string.nc_import_accounts_from)) - filesAppIntent.putExtra(KEY_ACCOUNT, accountString) + filesAppIntent.putExtra(KEY_ACCOUNT, accountName) filesAppIntent.putExtra(KEY_FILE_ID, fileId) startActivity(filesAppIntent) } else if (!link.isNullOrEmpty()) { diff --git a/app/src/main/java/com/nextcloud/talk/utils/AccountUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/AccountUtils.kt index b1fde6f91db..ac8345f6052 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/AccountUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/AccountUtils.kt @@ -16,6 +16,7 @@ import android.accounts.AccountManager import android.content.Context import android.content.pm.PackageManager import android.util.Log +import com.nextcloud.android.common.core.utils.AccountNameUtils import com.nextcloud.talk.R import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.data.user.model.User @@ -26,59 +27,63 @@ object AccountUtils { private val TAG = AccountUtils::class.java.simpleName private const val MIN_SUPPORTED_FILES_APP_VERSION = 30060151 + private const val FILES_KEY_USER_ID = "oc_id" + private const val FILES_KEY_BASE_URL = "oc_base_url" fun findAvailableAccountsOnDevice(users: List): List { val context = NextcloudTalkApplication.sharedApplication!!.applicationContext val accMgr = AccountManager.get(context) val accounts = accMgr.getAccountsByType(context.getString(R.string.nc_import_account_type)) - val accountsAvailable = ArrayList() - var accountFound: Boolean - for (account in accounts) { - accountFound = false + return accounts.filter { account -> + val canImport = users.isEmpty() || getInformationFromAccount(account).token != null + canImport && users.none { accMgr.isSameAccount(account, it) } + } + } - for (user in users) { - if (matchAccounts(getInformationFromAccount(account), user)) { - accountFound = true - break - } - } + fun findFilesAccountName(context: Context, user: User): String? { + val accMgr = AccountManager.get(context) + return accMgr.getAccountsByType(context.getString(R.string.nc_import_account_type)) + .firstOrNull { accMgr.isSameAccount(it, user) } + ?.name + } - if (!accountFound) { - accountsAvailable.add(account) - } + fun findUserForFilesAccount(context: Context, accountName: String, users: List): User? { + val accountType = context.getString(R.string.nc_import_account_type) + val accMgr = AccountManager.get(context) + val account = accMgr.getAccountsByType(accountType).firstOrNull { it.name == accountName } + ?: Account(accountName, accountType) + return users.firstOrNull { accMgr.isSameAccount(account, it) } + } + + fun buildAccountName(user: User): String? { + val username = user.username + val baseUrl = user.baseUrl + if (username == null || baseUrl == null) { + return null } - return accountsAvailable + return AccountNameUtils.build(username, AccountNameUtils.removeScheme(baseUrl)) } - private fun matchAccounts(importAccount: ImportAccount, user: User): Boolean { - var accountFound = false - if (importAccount.token != null) { - if (UriUtils.hasHttpProtocolPrefixed(importAccount.baseUrl!!)) { - if ( - user.username == importAccount.username && - user.baseUrl == importAccount.baseUrl - ) { - accountFound = true - } - } else { - if (user.username == importAccount.username && - ( - user.baseUrl == "http://" + importAccount.baseUrl || - user.baseUrl == "https://" + importAccount.baseUrl - ) - ) { - accountFound = true - } - } + private fun AccountManager.isSameAccount(account: Account, user: User): Boolean { + val userBaseUrl = user.baseUrl ?: return false + val filesBaseUrl = getUserDataOrNull(account, FILES_KEY_BASE_URL) + ?: AccountNameUtils.getServerPart(account.name) + val filesUserId = getUserDataOrNull(account, FILES_KEY_USER_ID) + val userId = user.userId + + return if (filesUserId != null && userId != null) { + AccountNameUtils.isSameAccount(filesBaseUrl, filesUserId, userBaseUrl, userId) } else { - accountFound = true + AccountNameUtils.isSameServer(filesBaseUrl, userBaseUrl) && + AccountNameUtils.getUserPart(account.name).equals(user.username, ignoreCase = true) } - - return accountFound } + private fun AccountManager.getUserDataOrNull(account: Account, key: String): String? = + runCatching { getUserData(account, key) }.getOrNull() + fun getAppNameBasedOnPackage(packageName: String): String { val context = NextcloudTalkApplication.sharedApplication!!.applicationContext val packageManager = context.packageManager @@ -97,7 +102,7 @@ object AccountUtils { return appName } - fun canWeOpenFilesApp(context: Context, accountName: String): Boolean { + fun resolveFilesAccountName(context: Context, user: User): String? { val pm = context.packageManager try { val packageInfo = pm.getPackageInfo(context.getString(R.string.nc_import_accounts_from), 0) @@ -109,11 +114,9 @@ object AccountUtils { ).signatures return if (Arrays.equals(ownSignatures, filesAppSignatures)) { - val accMgr = AccountManager.get(context) - val accounts = accMgr.getAccountsByType(context.getString(R.string.nc_import_account_type)) - accounts.any { it.name == accountName } + findFilesAccountName(context, user) } else { - true + buildAccountName(user) } } } catch (appNotFoundException: PackageManager.NameNotFoundException) { @@ -124,7 +127,7 @@ object AccountUtils { ) } - return false + return null } @Suppress("Detekt.TooGenericExceptionCaught") diff --git a/app/src/main/java/com/nextcloud/talk/utils/FileViewerUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/FileViewerUtils.kt index f820cdcce59..e6b4e53bc32 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/FileViewerUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/FileViewerUtils.kt @@ -33,7 +33,7 @@ import com.nextcloud.talk.fullscreenfile.FullScreenTextViewerActivity import com.nextcloud.talk.jobs.DownloadFileToCacheWorker import com.nextcloud.talk.mediaviewer.activities.MediaViewerActivity import com.nextcloud.talk.mediaviewer.model.MediaViewerItem -import com.nextcloud.talk.utils.AccountUtils.canWeOpenFilesApp +import com.nextcloud.talk.utils.AccountUtils.resolveFilesAccountName import com.nextcloud.talk.utils.Mimetype.IMAGE_GIF import com.nextcloud.talk.utils.Mimetype.IMAGE_HEIC import com.nextcloud.talk.utils.Mimetype.IMAGE_JPEG @@ -237,12 +237,8 @@ class FileViewerUtils(private val context: Context, private val user: User) { } fun openFileInFilesApp(link: String, keyID: String) { - val accountString = user.username + "@" + - user.baseUrl - ?.replace("https://", "") - ?.replace("http://", "") - - if (canWeOpenFilesApp(context, accountString)) { + val accountName = resolveFilesAccountName(context, user) + if (accountName != null) { val filesAppIntent = Intent(Intent.ACTION_VIEW, null) val componentName = ComponentName( context.getString(R.string.nc_import_accounts_from), @@ -251,7 +247,7 @@ class FileViewerUtils(private val context: Context, private val user: User) { filesAppIntent.component = componentName filesAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) filesAppIntent.setPackage(context.getString(R.string.nc_import_accounts_from)) - filesAppIntent.putExtra(KEY_ACCOUNT, accountString) + filesAppIntent.putExtra(KEY_ACCOUNT, accountName) filesAppIntent.putExtra(KEY_FILE_ID, keyID) context.startActivity(filesAppIntent) } else { diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index f4923c7345f..9733d0cf257 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2129,6 +2129,14 @@ + + + + + + + + @@ -2137,6 +2145,14 @@ + + + + + + + + @@ -2145,6 +2161,14 @@ + + + + + + + + From a9f8e7ca1fa9a8be26f7e5799f11cbdc4c087e9b Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 13 Nov 2026 10:57:55 +0100 Subject: [PATCH 2/2] update lib Signed-off-by: alperozturk96 --- app/build.gradle.kts | 4 +-- gradle/verification-metadata.xml | 49 ++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 10d0dd915e1..26c978a0036 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -336,8 +336,8 @@ dependencies { implementation("androidx.core:core-splashscreen:1.2.0") implementation("androidx.sharetarget:sharetarget:1.2.0") implementation("androidx.activity:activity-ktx:1.13.0") - implementation("com.github.nextcloud.android-common:ui:f6515c1c36") - implementation("com.github.nextcloud.android-common:core:f6515c1c36") + implementation("com.github.nextcloud.android-common:ui:580a84868ae2af10b2ace13dadc083f166047493") + implementation("com.github.nextcloud.android-common:core:580a84868ae2af10b2ace13dadc083f166047493") implementation("com.github.nextcloud-deps:android-talk-webrtc:155.8059.1") implementation("com.github.nextcloud-releases:talk-clients-vodozemac:0.0.2") diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9733d0cf257..02528221d9f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2129,6 +2129,14 @@ + + + + + + + + @@ -2145,6 +2153,14 @@ + + + + + + + + @@ -2161,6 +2177,14 @@ + + + + + + + + @@ -2409,6 +2433,11 @@ + + + + + @@ -3876,6 +3905,11 @@ + + + + + @@ -4661,11 +4695,21 @@ + + + + + + + + + + @@ -4951,6 +4995,11 @@ + + + + +