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 @@ -25,7 +25,7 @@ import com.owncloud.android.R
import com.owncloud.android.databinding.AddMemberFragmentBinding
import com.owncloud.android.domain.members.model.OCMember
import com.owncloud.android.domain.members.model.OCMemberType
import com.owncloud.android.presentation.spaces.members.SpaceRolesAdapter
import com.owncloud.android.presentation.roles.RolesAdapter

fun AddMemberFragmentBinding.showOrHideEmptyView(hasMembers: Boolean, searchMinLength: Int) {
membersRecyclerView.isVisible = hasMembers
Expand All @@ -48,9 +48,9 @@ fun AddMemberFragmentBinding.bindSelectedMember(member: OCMember) {
}
}

fun AddMemberFragmentBinding.bindRoles(rolesAdapter: SpaceRolesAdapter, selectedRoleId: String?) {
fun AddMemberFragmentBinding.bindRoles(rolesAdapter: RolesAdapter, selectedRoleId: String?) {
selectedRoleId?.let {
inviteMemberButton.isEnabled = true
confirmActionButton.isEnabled = true
rolesAdapter.setSelectedRole(it)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.owncloud.android.presentation.spaces.members
package com.owncloud.android.presentation.members

import android.view.LayoutInflater
import android.view.View
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.owncloud.android.presentation.spaces.members
package com.owncloud.android.presentation.members

import androidx.recyclerview.widget.DiffUtil
import com.owncloud.android.domain.members.model.OCMember
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.owncloud.android.presentation.spaces.members
package com.owncloud.android.presentation.roles

import android.view.LayoutInflater
import android.view.View
Expand All @@ -30,23 +30,23 @@ import com.owncloud.android.domain.roles.model.OCRole
import com.owncloud.android.domain.roles.model.OCRoleType
import com.owncloud.android.utils.PreferenceUtils

class SpaceRolesAdapter(
class RolesAdapter(
val onRoleSelected: ((OCRole) -> Unit)? = null
): RecyclerView.Adapter<SpaceRolesAdapter.SpaceRolesViewHolder>() {
): RecyclerView.Adapter<RolesAdapter.RolesViewHolder>() {

private var roles: List<OCRole> = emptyList()
private var selectedRoleId: String? = null

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SpaceRolesViewHolder {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RolesViewHolder {
val inflater = LayoutInflater.from(parent.context)

val view = inflater.inflate(R.layout.role_item, parent, false)
view.filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(parent.context)

return SpaceRolesViewHolder(view)
return RolesViewHolder(view)
}

override fun onBindViewHolder(holder: SpaceRolesViewHolder, position: Int) {
override fun onBindViewHolder(holder: RolesViewHolder, position: Int) {
val role = roles[position]

holder.binding.apply {
Expand Down Expand Up @@ -91,7 +91,7 @@ class SpaceRolesAdapter(
this.selectedRoleId = id
}

class SpaceRolesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
class RolesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val binding = RoleItemBinding.bind(itemView)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ import com.owncloud.android.extensions.openDatePickerDialog
import com.owncloud.android.extensions.showErrorInSnackbar
import com.owncloud.android.extensions.showOrHideEmptyView
import com.owncloud.android.extensions.toOCMember
import com.owncloud.android.presentation.spaces.members.SearchMembersAdapter
import com.owncloud.android.presentation.spaces.members.SpaceRolesAdapter
import com.owncloud.android.presentation.members.SearchMembersAdapter
import com.owncloud.android.presentation.roles.RolesAdapter
import com.owncloud.android.utils.DisplayUtils
import org.koin.androidx.viewmodel.ext.android.activityViewModel
import org.koin.core.parameter.parametersOf
Expand All @@ -62,7 +62,7 @@ class AddGraphShareFragment : Fragment(), SearchMembersAdapter.SearchMembersAdap
}

private lateinit var searchMembersAdapter: SearchMembersAdapter
private lateinit var rolesAdapter: SpaceRolesAdapter
private lateinit var rolesAdapter: RolesAdapter
private lateinit var recyclerView: RecyclerView

private var roles: List<OCRole> = emptyList()
Expand Down Expand Up @@ -97,8 +97,8 @@ class AddGraphShareFragment : Fragment(), SearchMembersAdapter.SearchMembersAdap
adapter = searchMembersAdapter
}

rolesAdapter = SpaceRolesAdapter(onRoleSelected = {
binding.inviteMemberButton.isEnabled = true
rolesAdapter = RolesAdapter(onRoleSelected = {
binding.confirmActionButton.isEnabled = true
graphShareViewModel.onRoleSelected(it)
})
binding.rolesRecyclerView.apply {
Expand Down Expand Up @@ -207,9 +207,9 @@ class AddGraphShareFragment : Fragment(), SearchMembersAdapter.SearchMembersAdap
binding.apply {
searchMemberLayout.visibility = View.GONE
addMemberLayout.visibility = View.VISIBLE
inviteMemberButton.visibility = View.VISIBLE
inviteMemberButton.text = getString(if (editMode) R.string.share_confirm_public_link_button else R.string.action_share)
inviteMemberButton.contentDescription =
confirmActionButton.visibility = View.VISIBLE
confirmActionButton.text = getString(if (editMode) R.string.share_confirm_public_link_button else R.string.action_share)
confirmActionButton.contentDescription =
getString(if (editMode) R.string.content_description_edit_share_button else R.string.content_description_create_share_button)
}
it.selectedMember?.let { member ->
Expand All @@ -234,7 +234,7 @@ class AddGraphShareFragment : Fragment(), SearchMembersAdapter.SearchMembersAdap
}
}

binding.inviteMemberButton.setOnClickListener {
binding.confirmActionButton.setOnClickListener {
uiState.selectedMember?.let { selectedMember ->
uiState.selectedRole?.let { selectedRole ->
if (editMode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,33 @@

package com.owncloud.android.presentation.spaces.members

import android.app.DatePickerDialog
import android.icu.util.Calendar
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
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.AddMemberFragmentBinding
import com.owncloud.android.domain.members.model.OCMember
import com.owncloud.android.domain.members.model.OCMemberType
import com.owncloud.android.domain.roles.model.OCRole
import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.domain.sharing.shares.model.MemberPermission
import com.owncloud.android.extensions.bindDatePickerDialog
import com.owncloud.android.extensions.bindRoles
import com.owncloud.android.extensions.bindSelectedMember
import com.owncloud.android.extensions.collectLatestLifecycleFlow
import com.owncloud.android.extensions.openDatePickerDialog
import com.owncloud.android.extensions.showErrorInSnackbar
import com.owncloud.android.extensions.showOrHideEmptyView
import com.owncloud.android.presentation.common.UIResult
import com.owncloud.android.presentation.members.SearchMembersAdapter
import com.owncloud.android.presentation.roles.RolesAdapter
import com.owncloud.android.utils.DisplayUtils
import org.koin.androidx.viewmodel.ext.android.activityViewModel
import org.koin.core.parameter.parametersOf
import timber.log.Timber
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.TimeZone

class AddMemberFragment: Fragment(), SearchMembersAdapter.SearchMembersAdapterListener {
private var _binding: AddMemberFragmentBinding? = null
Expand All @@ -60,7 +60,7 @@ class AddMemberFragment: Fragment(), SearchMembersAdapter.SearchMembersAdapterLi
}

private lateinit var searchMembersAdapter: SearchMembersAdapter
private lateinit var rolesAdapter: SpaceRolesAdapter
private lateinit var rolesAdapter: RolesAdapter
private lateinit var recyclerView: RecyclerView
private lateinit var roles: List<OCRole>

Expand All @@ -80,15 +80,26 @@ class AddMemberFragment: Fragment(), SearchMembersAdapter.SearchMembersAdapterLi

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

editMode = requireArguments().getBoolean(ARG_EDIT_MODE, false)
roles = requireArguments().getParcelableArrayList<OCRole>(ARG_ROLES) ?: arrayListOf()

searchMembersAdapter = SearchMembersAdapter(this)
recyclerView = binding.membersRecyclerView
recyclerView.apply {
layoutManager = LinearLayoutManager(requireContext())
adapter = searchMembersAdapter
}

editMode = requireArguments().getBoolean(ARG_EDIT_MODE, false)
roles = requireArguments().getParcelableArrayList<OCRole>(ARG_ROLES) ?: arrayListOf()
rolesAdapter = RolesAdapter(onRoleSelected = {
binding.confirmActionButton.isEnabled = true
spaceMembersViewModel.onRoleSelected(it)
})
binding.rolesRecyclerView.apply {
layoutManager = LinearLayoutManager(requireContext())
adapter = rolesAdapter
}
rolesAdapter.setRoles(roles)

if (editMode) {
val selectedMember = requireArguments().getParcelable<MemberPermission>(ARG_SELECTED_MEMBER)
Expand Down Expand Up @@ -118,19 +129,6 @@ class AddMemberFragment: Fragment(), SearchMembersAdapter.SearchMembersAdapterLi
}
}

private fun showOrHideEmptyView(hasMembers: Boolean) {
binding.membersRecyclerView.isVisible = hasMembers
binding.emptyDataParent.apply {
val shouldShow = !hasMembers && binding.searchBar.query.length >= searchMinLength
root.isVisible = shouldShow
if (shouldShow) {
listEmptyDatasetIcon.setImageResource(R.drawable.ic_share_generic_white)
listEmptyDatasetTitle.setText(R.string.members_search_failed)
listEmptyDatasetSubTitle.setText(R.string.members_search_empty)
}
}
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
requireActivity().setTitle(if (editMode) R.string.members_edit else R.string.members_add)
Expand All @@ -151,12 +149,12 @@ class AddMemberFragment: Fragment(), SearchMembersAdapter.SearchMembersAdapterLi
binding.membersRecyclerView.visibility = View.GONE
} else {
binding.indeterminateProgressBar.visibility = View.GONE
val listOfMembersFiltered = uiState.members.filter { member ->
!spaceMembers.any { spaceMember ->
spaceMember.id == "u:${member.id}" || spaceMember.id == "g:${member.id}" }
val spaceMemberIds = spaceMembers.mapTo(HashSet()) { it.id }
val listOfMembersFiltered = uiState.members.filterNot { member ->
"u:${member.id}" in spaceMemberIds || "g:${member.id}" in spaceMemberIds
}
val hasMembers = listOfMembersFiltered.isNotEmpty()
showOrHideEmptyView(hasMembers)
binding.showOrHideEmptyView(hasMembers, searchMinLength)
if (hasMembers) searchMembersAdapter.setMembers(listOfMembersFiltered)
uiState.error?.let {
Timber.e(uiState.error, "Failed to retrieve available users and groups")
Expand All @@ -170,30 +168,30 @@ class AddMemberFragment: Fragment(), SearchMembersAdapter.SearchMembersAdapterLi
binding.apply {
searchMemberLayout.visibility = View.GONE
addMemberLayout.visibility = View.VISIBLE
inviteMemberButton.visibility = View.VISIBLE
confirmActionButton.visibility = View.VISIBLE
}
it.selectedMember?.let { member ->
bindSelectedMember(member)
binding.bindSelectedMember(member)
}
it.selectedExpirationDate?.let { expirationDate ->
binding.expirationDateLayout.expirationDateValue.apply {
visibility = View.VISIBLE
text = DisplayUtils.displayDateToHumanReadable(expirationDate)
}
}
bindRoles(uiState.selectedRole?.id)
bindDatePickerDialog(uiState.selectedExpirationDate)
binding.bindRoles(rolesAdapter, uiState.selectedRole?.id)
bindDatePickerDialog(binding, uiState.selectedExpirationDate, spaceMembersViewModel::onExpirationDateSelected)

binding.expirationDateLayout.apply {
expirationDateLayout.setOnClickListener {
if (uiState.selectedExpirationDate != null) {
openDatePickerDialog(uiState.selectedExpirationDate)
openDatePickerDialog(binding, uiState.selectedExpirationDate, spaceMembersViewModel::onExpirationDateSelected)
} else {
expirationDateSwitch.isChecked = true
}
}
}
binding.inviteMemberButton.setOnClickListener {
binding.confirmActionButton.setOnClickListener {
uiState.selectedMember?.let { selectedMember ->
uiState.selectedRole?.let { selectedRole ->
if (editMode) {
Expand Down Expand Up @@ -228,77 +226,6 @@ class AddMemberFragment: Fragment(), SearchMembersAdapter.SearchMembersAdapterLi
}
}

private fun bindSelectedMember(member: OCMember) {
binding.selectedMemberLayout.apply {
memberIcon.setImageResource(if (member.type == OCMemberType.GROUP) R.drawable.ic_group else R.drawable.ic_user)
memberName.text = member.displayName
memberRole.text = member.surname
}
}

private fun bindRoles(selectedRoleId: String?) {
rolesAdapter = SpaceRolesAdapter(onRoleSelected = {
binding.inviteMemberButton.isEnabled = true
spaceMembersViewModel.onRoleSelected(it)
})
binding.rolesRecyclerView.apply {
layoutManager = LinearLayoutManager(requireContext())
adapter = rolesAdapter
}
rolesAdapter.setRoles(roles)
selectedRoleId?.let {
binding.inviteMemberButton.isEnabled = true
rolesAdapter.setSelectedRole(it)
}
}

private fun bindDatePickerDialog(expirationDate: String?) {
binding.expirationDateLayout.expirationDateSwitch.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
openDatePickerDialog(expirationDate)
} else {
binding.expirationDateLayout.expirationDateValue.visibility = View.GONE
spaceMembersViewModel.onExpirationDateSelected(null)
}
}
}

private fun openDatePickerDialog(expirationDate: String?) {
val calendar = Calendar.getInstance()
val formatter = SimpleDateFormat(DisplayUtils.DATE_FORMAT_ISO, Locale.ROOT).apply {
timeZone = TimeZone.getTimeZone("UTC")
}

expirationDate?.let {
calendar.time = formatter.parse(it)
}

DatePickerDialog(
requireContext(),
{ _, selectedYear, selectedMonth, selectedDay ->
calendar.set(selectedYear, selectedMonth, selectedDay, 23, 59, 59)
calendar.set(Calendar.MILLISECOND, 999)
val isoExpirationDate = formatter.format(calendar.time)
spaceMembersViewModel.onExpirationDateSelected(isoExpirationDate)
binding.expirationDateLayout.expirationDateValue.apply {
visibility = View.VISIBLE
text = DisplayUtils.displayDateToHumanReadable(isoExpirationDate)
}
},
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
).apply {
datePicker.minDate = Calendar.getInstance().timeInMillis
show()
setOnCancelListener {
if (expirationDate == null) {
binding.expirationDateLayout.expirationDateSwitch.isChecked = false
}
}
}
}

private fun bindEditMode(member: MemberPermission, roles: List<OCRole>) {
selectedMemberId = member.id
spaceMembersViewModel.onMemberSelected(member)
Expand All @@ -310,7 +237,7 @@ class AddMemberFragment: Fragment(), SearchMembersAdapter.SearchMembersAdapterLi
spaceMembersViewModel.onExpirationDateSelected(expirationDate)
binding.expirationDateLayout.expirationDateSwitch.isChecked = true
}
binding.inviteMemberButton.text = getString(R.string.share_confirm_public_link_button)
binding.confirmActionButton.text = getString(R.string.share_confirm_public_link_button)
}

companion object {
Expand Down
Loading
Loading