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 @@ -3,7 +3,7 @@
*
* @author Jorge Aguado Recio
*
* Copyright (C) 2025 ownCloud GmbH.
* Copyright (C) 2026 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
Expand All @@ -25,21 +25,42 @@ import android.view.Menu
import android.view.MenuItem
import androidx.fragment.app.transaction
import com.owncloud.android.R
import com.owncloud.android.databinding.MembersActivityBinding
import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.ui.activity.FileActivity
import com.owncloud.android.utils.DisplayUtils

class SpaceMembersActivity: FileActivity() {

private lateinit var binding: MembersActivityBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContentView(R.layout.members_activity)
binding = MembersActivityBinding.inflate(layoutInflater)
setContentView(binding.root)

setupStandardToolbar(title = null, displayHomeAsUpEnabled = true, homeButtonEnabled = true, displayShowTitleEnabled = true)

supportActionBar?.setHomeActionContentDescription(R.string.common_back)

val currentSpace = intent.getParcelableExtra<OCSpace>(EXTRA_SPACE)
val currentSpace = intent.getParcelableExtra<OCSpace>(EXTRA_SPACE) ?: return
binding.apply {
itemName.text = currentSpace.name
currentSpace.quota?.let { quota ->
val usedQuota = quota.used
val totalQuota = quota.total
itemSize.text = when {
usedQuota == null -> getString(R.string.drawer_unavailable_used_storage)
totalQuota == 0L -> DisplayUtils.bytesToHumanReadable(usedQuota, baseContext, true)
else -> getString(
R.string.drawer_quota,
DisplayUtils.bytesToHumanReadable(usedQuota, baseContext, true),
DisplayUtils.bytesToHumanReadable(totalQuota, baseContext, true),
quota.getRelative().toString())
}
}
}

supportFragmentManager.transaction {
if (savedInstanceState == null && currentSpace != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* @author Jorge Aguado Recio
*
* Copyright (C) 2025 ownCloud GmbH.
* Copyright (C) 2026 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
Expand All @@ -27,13 +27,11 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.owncloud.android.R
import com.owncloud.android.databinding.MembersFragmentBinding
import com.owncloud.android.domain.roles.model.OCRole
import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.extensions.collectLatestLifecycleFlow
import com.owncloud.android.presentation.common.UIResult
import com.owncloud.android.utils.DisplayUtils
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf

Expand Down Expand Up @@ -96,20 +94,16 @@ class SpaceMembersFragment : Fragment() {
}
}

val currentSpace = requireArguments().getParcelable<OCSpace>(ARG_CURRENT_SPACE) ?: return
binding.apply {
itemName.text = currentSpace.name
currentSpace.quota?.let { quota ->
val usedQuota = quota.used
val totalQuota = quota.total
itemSize.text = when {
usedQuota == null -> getString(R.string.drawer_unavailable_used_storage)
totalQuota == 0L -> DisplayUtils.bytesToHumanReadable(usedQuota, requireContext(), true)
else -> getString(
R.string.drawer_quota,
DisplayUtils.bytesToHumanReadable(usedQuota, requireContext(), true),
DisplayUtils.bytesToHumanReadable(totalQuota, requireContext(), true),
quota.getRelative().toString())
collectLatestLifecycleFlow(spaceMembersViewModel.spacePermissions) { event ->
event?.let {
when (val uiResult = event.peekContent()) {
is UIResult.Success -> {
uiResult.data?.let { spacePermissions ->
if (DRIVES_CREATE_PERMISSION in spacePermissions) { binding.addMemberButton.visibility = View.VISIBLE }
}
}
is UIResult.Loading -> { }
is UIResult.Error -> { }
}
}
}
Expand All @@ -118,6 +112,7 @@ class SpaceMembersFragment : Fragment() {
companion object {
private const val ARG_CURRENT_SPACE = "CURRENT_SPACE"
private const val ARG_ACCOUNT_NAME = "ACCOUNT_NAME"
private const val DRIVES_CREATE_PERMISSION = "libre.graph/driveItem/permissions/create"

fun newInstance(
accountName: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* @author Jorge Aguado Recio
*
* Copyright (C) 2025 ownCloud GmbH.
* Copyright (C) 2026 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
Expand All @@ -26,6 +26,7 @@ import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.domain.spaces.model.SpaceMembers
import com.owncloud.android.domain.spaces.usecases.GetSpaceMembersUseCase
import com.owncloud.android.domain.roles.usecases.GetRolesAsyncUseCase
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 @@ -36,6 +37,7 @@ import kotlinx.coroutines.flow.StateFlow
class SpaceMembersViewModel(
private val getRolesAsyncUseCase: GetRolesAsyncUseCase,
private val getSpaceMembersUseCase: GetSpaceMembersUseCase,
private val getSpacePermissionsAsyncUseCase: GetSpacePermissionsAsyncUseCase,
private val accountName: String,
private val space: OCSpace,
private val coroutineDispatcherProvider: CoroutinesDispatcherProvider
Expand All @@ -47,6 +49,9 @@ class SpaceMembersViewModel(
private val _spaceMembers = MutableStateFlow<Event<UIResult<SpaceMembers>>?>(null)
val spaceMembers: StateFlow<Event<UIResult<SpaceMembers>>?> = _spaceMembers

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

init {
runUseCaseWithResult(
coroutineDispatcher = coroutineDispatcherProvider.io,
Expand All @@ -56,6 +61,16 @@ class SpaceMembersViewModel(
showLoading = false,
requiresConnection = true
)

runUseCaseWithResult(
coroutineDispatcher = coroutineDispatcherProvider.io,
flow = _spacePermissions,
useCase = getSpacePermissionsAsyncUseCase,
useCaseParams = GetSpacePermissionsAsyncUseCase.Params(accountName = accountName, spaceId = space.id),
showLoading = false,
requiresConnection = true
)

}

fun getSpaceMembers() = runUseCaseWithResult(
Expand Down
49 changes: 46 additions & 3 deletions owncloudApp/src/main/res/layout/members_activity.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?><!--
ownCloud Android client application

Copyright (C) 2025 ownCloud GmbH.
Copyright (C) 2026 ownCloud GmbH.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
Expand All @@ -16,8 +16,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/members_activity_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
Expand All @@ -26,6 +26,49 @@

<include layout="@layout/owncloud_toolbar" />

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/item_header_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/standard_padding">

<ImageView
android:id="@+id/item_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_menu_space"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>

<TextView
android:id="@+id/item_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/standard_half_margin"
android:layout_marginStart="@dimen/standard_half_margin"
android:ellipsize="middle"
android:singleLine="true"
android:text="@string/placeholder_filename"
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@id/item_icon"
app:layout_constraintTop_toTopOf="parent"/>

<TextView
android:id="@+id/item_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/standard_half_margin"
android:text="@string/placeholder_filesize"
android:textColor="@color/list_item_lastmod_and_filesize_text"
android:textSize="14sp"
app:layout_constraintStart_toEndOf="@id/item_icon"
app:layout_constraintTop_toBottomOf="@+id/item_name"/>

</androidx.constraintlayout.widget.ConstraintLayout>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
Expand Down
105 changes: 35 additions & 70 deletions owncloudApp/src/main/res/layout/members_fragment.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?><!--
ownCloud Android client application

Copyright (C) 2025 ownCloud GmbH.
Copyright (C) 2026 ownCloud GmbH.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
Expand All @@ -25,91 +25,56 @@
tools:context=".presentation.spaces.members.SpaceMembersActivity">

<LinearLayout
android:id="@+id/members_section"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/item_header_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/standard_padding">

<ImageView
android:id="@+id/item_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_menu_space"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
android:layout_height="match_parent"
android:background="@color/actionbar_start_color">

<TextView
android:id="@+id/item_name"
android:id="@+id/members_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/standard_half_margin"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:gravity="center"
android:text="@string/space_members"
android:layout_marginStart="@dimen/standard_half_margin"
android:ellipsize="middle"
android:singleLine="true"
android:text="@string/placeholder_filename"
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@id/item_icon"
android:textAllCaps="true"
android:textColor="@color/white"
android:textStyle="bold"
android:accessibilityHeading="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

<TextView
android:id="@+id/item_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/standard_half_margin"
android:text="@string/placeholder_filesize"
android:textColor="@color/list_item_lastmod_and_filesize_text"
android:textSize="14sp"
app:layout_constraintStart_toEndOf="@id/item_icon"
app:layout_constraintTop_toBottomOf="@+id/item_name"/>
<ImageButton
android:id="@+id/add_member_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="@dimen/standard_padding"
android:background="@color/transparent"
android:src="@drawable/ic_add"
android:contentDescription="@string/content_description_add_member"
android:visibility="gone"
android:focusable="true"
android:clickable="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible"/>

</androidx.constraintlayout.widget.ConstraintLayout>

<LinearLayout
android:id="@+id/members_section"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/members_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/actionbar_start_color">

<TextView
android:id="@+id/members_title"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:gravity="center"
android:text="@string/space_members"
android:layout_marginStart="@dimen/standard_half_margin"
android:textAllCaps="true"
android:textColor="@color/white"
android:textStyle="bold"
android:accessibilityHeading="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/members_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="vertical"
android:visibility="visible"
tools:visibility="visible"/>

</LinearLayout>
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="vertical"
android:visibility="visible"
tools:visibility="visible"/>

</LinearLayout>

Expand Down
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 @@ -830,6 +830,7 @@
<string name="content_description_member_user">User %1$s</string>
<string name="content_description_member_group">Group %1$s</string>
<string name="content_description_member_expiration_date">Expires %1$s</string>
<string name="content_description_add_member">Add new member</string>

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