diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphShareFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphShareFragment.kt index 62e9f23f9a9..5595b72659e 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphShareFragment.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphShareFragment.kt @@ -55,6 +55,7 @@ class GraphShareFragment : Fragment() { private var roles: List = emptyList() private var listener: GraphShareFragmentListener? = null + private var canRemoveShares: Boolean = false override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = MembersFragmentBinding.inflate(inflater, container, false) @@ -107,6 +108,7 @@ class GraphShareFragment : Fragment() { private fun subscribeToViewModels() { observeRoles() observeShares() + observeSpacePermissions() observeAddShareResult() } @@ -139,7 +141,7 @@ class GraphShareFragment : Fragment() { val hasMembers = it.members.isNotEmpty() binding.membersRecyclerView.isVisible = hasMembers binding.noSharesMessage.isVisible = !hasMembers - graphSharesAdapter.setShares(it.members, it.roles) + graphSharesAdapter.setShares(it.members, it.roles, canRemoveShares) binding.swipeRefreshMembers.isRefreshing = false } } @@ -154,6 +156,28 @@ class GraphShareFragment : Fragment() { } } + private fun observeSpacePermissions() { + collectLatestLifecycleFlow(graphShareViewModel.spacePermissions) { event -> + event?.let { + when (val uiResult = event.peekContent()) { + is UIResult.Success -> { + uiResult.data?.let { spacePermissions -> + checkPermissions(spacePermissions) + } + } + is UIResult.Loading -> { } + is UIResult.Error -> { + Timber.e(uiResult.error, "Failed to retrieve space permissions") + } + } + } + } + } + + private fun checkPermissions(spacePermissions: List) { + canRemoveShares = DRIVES_DELETE_PERMISSION in spacePermissions + } + private fun observeAddShareResult() { collectLatestLifecycleFlow(graphShareViewModel.addShareResultFlow) { event -> event?.peekContent()?.let { uiResult -> @@ -176,6 +200,7 @@ class GraphShareFragment : Fragment() { companion object { private const val ARG_FILE = "FILE" private const val ARG_ACCOUNT_NAME = "ACCOUNT_NAME" + private const val DRIVES_DELETE_PERMISSION = "libre.graph/driveItem/permissions/delete" fun newInstance(file: OCFile, accountName: String): GraphShareFragment { val args = Bundle().apply { diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphShareViewModel.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphShareViewModel.kt index 4b683896144..5e29b0f9516 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphShareViewModel.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphShareViewModel.kt @@ -35,6 +35,7 @@ import com.owncloud.android.domain.sharing.shares.usecases.AddGraphShareAsyncUse import com.owncloud.android.domain.sharing.shares.usecases.GetGraphSharesAsyncUseCase import com.owncloud.android.domain.sharing.shares.model.OCPermissions import com.owncloud.android.domain.user.usecases.GetUserIdAsyncUseCase +import com.owncloud.android.domain.spaces.usecases.GetSpacePermissionsAsyncUseCase import com.owncloud.android.domain.utils.Event import com.owncloud.android.extensions.ViewModelExt.runUseCaseWithResult import com.owncloud.android.presentation.common.UIResult @@ -55,6 +56,7 @@ class GraphShareViewModel( private val getStoredCapabilitiesUseCase: GetStoredCapabilitiesUseCase, private val searchMembersUseCase: SearchMembersUseCase, private val getUserIdAsyncUseCase: GetUserIdAsyncUseCase, + private val getSpacePermissionsAsyncUseCase: GetSpacePermissionsAsyncUseCase, private val accountName: String, private val file: OCFile, private val coroutineDispatcherProvider: CoroutinesDispatcherProvider, @@ -81,6 +83,9 @@ class GraphShareViewModel( private var searchJob: Job? = null var capabilities: OCCapability? = null + private val _spacePermissions = MutableStateFlow>>?>(null) + val spacePermissions: StateFlow>>?> = _spacePermissions + init { runUseCaseWithResult( coroutineDispatcher = coroutineDispatcherProvider.io, @@ -98,6 +103,24 @@ class GraphShareViewModel( viewModelScope.launch(coroutineDispatcherProvider.io) { capabilities = getStoredCapabilitiesUseCase(GetStoredCapabilitiesUseCase.Params(accountName)) } + getSpacePermissions() + } + + fun getSpacePermissions() { + val spaceId = file.spaceId + if (spaceId == null) { + _spacePermissions.update { Event(UIResult.Error(error = IncompleteFileDataException())) } + return + } + + runUseCaseWithResult( + coroutineDispatcher = coroutineDispatcherProvider.io, + flow = _spacePermissions, + useCase = getSpacePermissionsAsyncUseCase, + useCaseParams = GetSpacePermissionsAsyncUseCase.Params(accountName = accountName, spaceId = spaceId), + showLoading = false, + requiresConnection = true + ) } fun getGraphShares() { diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphSharesAdapter.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphSharesAdapter.kt index bc765fe678c..0991e03da19 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphSharesAdapter.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphSharesAdapter.kt @@ -37,6 +37,7 @@ class GraphSharesAdapter : RecyclerView.Adapter = emptyList() private var rolesMap: Map = emptyMap() + private var canRemoveShares = false override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GraphShareViewHolder { val inflater = LayoutInflater.from(parent.context) @@ -58,6 +59,11 @@ class GraphSharesAdapter : RecyclerView.Adapter, roles: List) { + fun setShares(shares: List, roles: List, canRemoveShares: Boolean) { + val hasUserPermissionsChanged = this.canRemoveShares != canRemoveShares + this.canRemoveShares = canRemoveShares this.rolesMap = roles.associate { it.id to it.displayName } val sortedShares = shares.sortedWith( compareBy { it.isGroup } .thenBy { it.displayName.lowercase() } ) - val diffResult = DiffUtil.calculateDiff(GraphSharesDiffUtil(this.shares, sortedShares)) + val diffResult = DiffUtil.calculateDiff(GraphSharesDiffUtil(this.shares, sortedShares, hasUserPermissionsChanged)) this.shares = sortedShares diffResult.dispatchUpdatesTo(this) } diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphSharesDiffUtil.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphSharesDiffUtil.kt index 39bf62427ee..20f330211a7 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphSharesDiffUtil.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/GraphSharesDiffUtil.kt @@ -26,6 +26,7 @@ import com.owncloud.android.domain.sharing.shares.model.MemberPermission class GraphSharesDiffUtil( private val oldList: List, private val newList: List, + private val hasUserPermissionsChanged: Boolean = false, ) : DiffUtil.Callback() { override fun getOldListSize(): Int = oldList.size @@ -36,5 +37,5 @@ class GraphSharesDiffUtil( oldList[oldItemPosition].id == newList[newItemPosition].id override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = - oldList[oldItemPosition] == newList[newItemPosition] + oldList[oldItemPosition] == newList[newItemPosition] && !hasUserPermissionsChanged } diff --git a/owncloudApp/src/main/res/values/strings.xml b/owncloudApp/src/main/res/values/strings.xml index 1e3d2b988c6..aac07aedfb0 100644 --- a/owncloudApp/src/main/res/values/strings.xml +++ b/owncloudApp/src/main/res/values/strings.xml @@ -729,6 +729,7 @@ Remove password Generate password Copy password + Remove share %1$s Create a shortcut URL