Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class GraphShareFragment : Fragment() {

private var roles: List<OCRole> = 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)
Expand Down Expand Up @@ -107,6 +108,7 @@ class GraphShareFragment : Fragment() {
private fun subscribeToViewModels() {
observeRoles()
observeShares()
observeSpacePermissions()
observeAddShareResult()
}

Expand Down Expand Up @@ -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
}
}
Expand All @@ -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<String>) {
canRemoveShares = DRIVES_DELETE_PERMISSION in spacePermissions
}

private fun observeAddShareResult() {
collectLatestLifecycleFlow(graphShareViewModel.addShareResultFlow) { event ->
event?.peekContent()?.let { uiResult ->
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -81,6 +83,9 @@ class GraphShareViewModel(
private var searchJob: Job? = null
var capabilities: OCCapability? = null

private val _spacePermissions = MutableStateFlow<Event<UIResult<List<String>>>?>(null)
val spacePermissions: StateFlow<Event<UIResult<List<String>>>?> = _spacePermissions

init {
runUseCaseWithResult(
coroutineDispatcher = coroutineDispatcherProvider.io,
Expand All @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class GraphSharesAdapter : RecyclerView.Adapter<GraphSharesAdapter.GraphShareVie

private var shares: List<MemberPermission> = emptyList()
private var rolesMap: Map<String, String> = emptyMap()
private var canRemoveShares = false

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GraphShareViewHolder {
val inflater = LayoutInflater.from(parent.context)
Expand All @@ -58,6 +59,11 @@ class GraphSharesAdapter : RecyclerView.Adapter<GraphSharesAdapter.GraphShareVie
)
memberRole.text = roleNames.joinToString(", ")

removeMemberButton.apply {
contentDescription = holder.itemView.context.getString(R.string.content_description_remove_share_button, share.displayName)
isVisible = canRemoveShares
}

val hasExpirationDate = share.expirationDateTime != null
expirationCalendarIcon.isVisible = hasExpirationDate
expirationDate.isVisible = hasExpirationDate
Expand All @@ -71,13 +77,15 @@ class GraphSharesAdapter : RecyclerView.Adapter<GraphSharesAdapter.GraphShareVie

override fun getItemCount(): Int = shares.size

fun setShares(shares: List<MemberPermission>, roles: List<OCRole>) {
fun setShares(shares: List<MemberPermission>, roles: List<OCRole>, canRemoveShares: Boolean) {
val hasUserPermissionsChanged = this.canRemoveShares != canRemoveShares
this.canRemoveShares = canRemoveShares
this.rolesMap = roles.associate { it.id to it.displayName }
val sortedShares = shares.sortedWith(
compareBy<MemberPermission> { 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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.owncloud.android.domain.sharing.shares.model.MemberPermission
class GraphSharesDiffUtil(
private val oldList: List<MemberPermission>,
private val newList: List<MemberPermission>,
private val hasUserPermissionsChanged: Boolean = false,
) : DiffUtil.Callback() {

override fun getOldListSize(): Int = oldList.size
Expand All @@ -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
}
1 change: 1 addition & 0 deletions owncloudApp/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,7 @@
<string name="content_description_remove_password_button">Remove password</string>
<string name="content_description_generate_password_button">Generate password</string>
<string name="content_description_copy_password_button">Copy password</string>
<string name="content_description_remove_share_button">Remove share %1$s</string>

<string name="create_shortcut_dialog_title">Create a shortcut</string>
<string name="create_shortcut_dialog_url">URL</string>
Expand Down