Skip to content
Merged
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ ownCloud admins and users.
* Enhancement - New field "last usage" in database: [#4173](https://github.com/owncloud/android/issues/4173)
* Enhancement - Use invoke operator to execute usecases: [#4179](https://github.com/owncloud/android/pull/4179)
* Enhancement - Deep link open app correctly: [#4181](https://github.com/owncloud/android/issues/4181)
* Enhancement - Select user and navigate to file when opening via deep link: [#4194](https://github.com/owncloud/android/issues/4194)

## Details

Expand Down Expand Up @@ -161,6 +162,14 @@ ownCloud admins and users.
https://github.com/owncloud/android/issues/4181
https://github.com/owncloud/android/pull/4191

* Enhancement - Select user and navigate to file when opening via deep link: [#4194](https://github.com/owncloud/android/issues/4194)

Select the correct user owner of the deep link file, managing possible errors
and navigating to the correct file.

https://github.com/owncloud/android/issues/4194
https://github.com/owncloud/android/pull/4212

# Changelog for ownCloud Android Client [4.1.1] (2023-10-18)

The following sections list the changes in ownCloud Android Client 4.1.1 relevant to
Expand Down
6 changes: 6 additions & 0 deletions changelog/unreleased/4212
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Select user and navigate to file when opening via deep link

Select the correct user owner of the deep link file, managing possible errors and navigating to the correct file.

https://github.com/owncloud/android/issues/4194
https://github.com/owncloud/android/pull/4212
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.google.android.material.snackbar.Snackbar
import com.owncloud.android.R
import com.owncloud.android.data.providers.implementation.OCSharedPreferencesProvider
Expand All @@ -61,6 +64,9 @@ import com.owncloud.android.ui.dialog.ShareLinkToDialog
import com.owncloud.android.utils.CONFIGURATION_DEVICE_PROTECTION
import com.owncloud.android.utils.MimetypeIconUtil
import com.owncloud.android.utils.UriUtilsKt.getExposedFileUriForOCFile
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
import timber.log.Timber
import java.io.File
Expand Down Expand Up @@ -436,3 +442,15 @@ fun Activity.openOCFile(ocFile: OCFile) {
showErrorInSnackbar(genericErrorMessageId = R.string.file_list_no_app_for_file_type, anfe)
}
}

fun <T> FragmentActivity.collectLatestLifecycleFlow(
flow: Flow<T>,
lifecycleState: Lifecycle.State = Lifecycle.State.STARTED,
collect: suspend (T) -> Unit
) {
lifecycleScope.launch {
repeatOnLifecycle(lifecycleState) {
flow.collectLatest(collect)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ import com.owncloud.android.R
import com.owncloud.android.databinding.MainFileListFragmentBinding
import com.owncloud.android.datamodel.ThumbnailsCacheManager
import com.owncloud.android.domain.appregistry.model.AppRegistryMimeType
import com.owncloud.android.domain.exceptions.DeepLinkException
import com.owncloud.android.domain.exceptions.InstanceNotConfiguredException
import com.owncloud.android.domain.exceptions.TooEarlyException
import com.owncloud.android.domain.files.model.FileListOption
Expand Down Expand Up @@ -621,33 +620,11 @@ class MainFileListFragment : Fragment(),
}
}

observeDeepLink()

/* TransfersViewModel observables */
observeTransfers()

}

private fun observeDeepLink() {
collectLatestLifecycleFlow(fileOperationsViewModel.deepLinkFlow) {
val uiResult = it?.peekContent()
if (uiResult is UIResult.Error) {
showMessageInSnackbar(
getString(
if (uiResult.error is DeepLinkException) {
R.string.invalid_deep_link_format
} else {
R.string.default_error_msg
}
)
)
} else if (uiResult is UIResult.Success) {
//TODO "Remove this message when end with managing the deep links"
showMessageInSnackbar("Deep link managed correctly")
}
}
}

private fun observeTransfers() {
val maxUploadsToRefresh = resources.getInteger(R.integer.max_uploads_to_refresh)
collectLatestLifecycleFlow(transfersViewModel.transfersWithSpaceStateFlow) { transfers ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ class FileOperationsViewModel(
}
}

fun handleDeepLink(uri: Uri, accountName: String) {
runUseCaseWithResult(
coroutineDispatcher = coroutinesDispatcherProvider.io,
showLoading = true,
flow = _deepLinkFlow,
useCase = manageDeepLinkUseCase,
useCaseParams = ManageDeepLinkUseCase.Params(URI(uri.toString()), accountName),
)
}

private fun createFolderOperation(fileOperation: FileOperation.CreateFolder) {
runOperation(
Expand Down Expand Up @@ -309,13 +318,4 @@ class FileOperationsViewModel(
}
}
}

fun handleDeepLink(uri: Uri) {
runUseCaseWithResult(
coroutineDispatcher = coroutinesDispatcherProvider.io,
flow = _deepLinkFlow,
useCase = manageDeepLinkUseCase,
useCaseParams = ManageDeepLinkUseCase.Params(URI(uri.toString())),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ import com.owncloud.android.data.providers.SharedPreferencesProvider
import com.owncloud.android.databinding.ActivityMainBinding
import com.owncloud.android.domain.camerauploads.model.UploadBehavior
import com.owncloud.android.domain.capabilities.model.OCCapability
import com.owncloud.android.domain.exceptions.DeepLinkException
import com.owncloud.android.domain.exceptions.FileNotFoundException
import com.owncloud.android.domain.exceptions.SSLRecoverablePeerUnverifiedException
import com.owncloud.android.domain.exceptions.UnauthorizedException
import com.owncloud.android.domain.files.model.FileListOption
Expand All @@ -64,6 +66,7 @@ import com.owncloud.android.domain.files.model.OCFile.Companion.ROOT_PARENT_ID
import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.domain.utils.Event
import com.owncloud.android.extensions.checkPasscodeEnforced
import com.owncloud.android.extensions.collectLatestLifecycleFlow
import com.owncloud.android.extensions.isDownloadPending
import com.owncloud.android.extensions.manageOptionLockSelected
import com.owncloud.android.extensions.observeWorkerTillItFinishes
Expand All @@ -79,6 +82,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode
import com.owncloud.android.lib.resources.status.OwnCloudVersion
import com.owncloud.android.operations.SyncProfileOperation
import com.owncloud.android.presentation.authentication.AccountUtils.getCurrentOwnCloudAccount
import com.owncloud.android.presentation.capabilities.CapabilityViewModel
import com.owncloud.android.presentation.common.UIResult
import com.owncloud.android.presentation.conflicts.ConflictsResolveActivity
Expand Down Expand Up @@ -1664,6 +1668,8 @@ class FileDisplayActivity : FileActivity(),
}

private fun startListeningToOperations() {
onDeepLinkManaged()

fileOperationsViewModel.copyFileLiveData.observe(this, Event.EventObserver {
onCopyFileOperationFinish(it)
})
Expand Down Expand Up @@ -1768,8 +1774,71 @@ class FileDisplayActivity : FileActivity(),

private fun handleDeepLink() {
intent.data?.let { uri ->
fileOperationsViewModel.handleDeepLink(uri)
intent.data = null
fileOperationsViewModel.handleDeepLink(uri, getCurrentOwnCloudAccount(baseContext).name)
}
}

private fun onDeepLinkManaged() {
collectLatestLifecycleFlow(fileOperationsViewModel.deepLinkFlow) {
it?.getContentIfNotHandled()?.let { uiResult ->
when (uiResult) {
is UIResult.Loading -> {
showLoadingDialog(R.string.deep_link_loading)
}
is UIResult.Success -> {
intent?.data = null
dismissLoadingDialog()
uiResult.data?.let { it1 -> manageItem(it1) }
}
is UIResult.Error -> {
dismissLoadingDialog()
if (uiResult.error is FileNotFoundException) {
showMessageInSnackbar(message = getString(R.string.deep_link_user_no_access))
changeUser()
} else {
showMessageInSnackbar(message = getString(
if (uiResult.error is DeepLinkException) {
R.string.invalid_deep_link_format
} else {
R.string.default_error_msg
}
))
}
}
}
}
}
}

private fun changeUser() {
val currentUser = getCurrentOwnCloudAccount(this)
val usersChecked = intent?.getStringArrayListExtra(KEY_DEEP_LINK_ACCOUNTS_CHECKED) ?: arrayListOf()
usersChecked.add(currentUser.name)
com.owncloud.android.presentation.authentication.AccountUtils.getAccounts(this).forEach {
if (!usersChecked.contains(it.name)) {
MainApp.initDependencyInjection()
val i = Intent(
this,
FileDisplayActivity::class.java
)
i.data = intent?.data
i.putExtra(EXTRA_ACCOUNT, it)
i.putExtra(KEY_DEEP_LINK_ACCOUNTS_CHECKED, usersChecked)
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(i)
}
}
}

private fun manageItem(file: OCFile) {
setFile(file)
account = com.owncloud.android.presentation.authentication.AccountUtils.getOwnCloudAccountByName(this, file.owner)

if (file.isFolder) {
refreshListOfFilesFragment()
} else {
initFragmentsWithFile()
onFileClicked(file)
}
}

Expand All @@ -1783,6 +1852,7 @@ class FileDisplayActivity : FileActivity(),
private const val KEY_WAITING_TO_SEND = "WAITING_TO_SEND"
private const val KEY_UPLOAD_HELPER = "FILE_UPLOAD_HELPER"
private const val KEY_FILE_LIST_OPTION = "FILE_LIST_OPTION"
const val KEY_DEEP_LINK_ACCOUNTS_CHECKED = "DEEP_LINK_ACCOUNTS_CHECKED"

private const val CUSTOM_DIALOG_TAG = "CUSTOM_DIALOG"

Expand Down
2 changes: 2 additions & 0 deletions owncloudApp/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,8 @@

<!-- DeepLinks -->
<string name="invalid_deep_link_format">Invalid link format</string>
<string name="deep_link_user_no_access">The user doesn\'t have access to file</string>
<string name="deep_link_loading">Opening file from link</string>

<string name="fab_refresh_text">Refresh</string>
<string name="fab_refresh_sync_in_progress">Synchronization already in progress</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2023 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.owncloud.android.lib.common.http.methods.webdav.properties

import at.bitfire.dav4jvm.Property
import at.bitfire.dav4jvm.PropertyFactory
import at.bitfire.dav4jvm.XmlUtils
import org.xmlpull.v1.XmlPullParser

data class OCFileId(val fileId: String) : Property {
class Factory : PropertyFactory {
override fun getName() = NAME

override fun create(parser: XmlPullParser): OCFileId? {
XmlUtils.readText(parser)?.let {
return OCFileId(it)
}
return null
}
}

companion object {
@JvmField
val NAME = Property.Name(XmlUtils.NS_OWNCLOUD, "fileid")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* ownCloud Android Library is available under MIT license
* Copyright (C) 2023 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.owncloud.android.lib.common.http.methods.webdav.properties

import at.bitfire.dav4jvm.Property
import at.bitfire.dav4jvm.PropertyFactory
import at.bitfire.dav4jvm.XmlUtils
import org.xmlpull.v1.XmlPullParser

data class OCMetaPathForUser(val path: String) : Property {
class Factory : PropertyFactory {
override fun getName() = NAME

override fun create(parser: XmlPullParser): OCMetaPathForUser? {
XmlUtils.readText(parser)?.let {
return OCMetaPathForUser(it)
}
return null
}
}

companion object {
@JvmField
val NAME = Property.Name(XmlUtils.NS_OWNCLOUD, "meta-path-for-user")
}
}
Loading