diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index c769b85c431610f203cd1e901bf18ccfe28afe5e..cf60c06c09f1dfe0f407b6b0ea8a85c2a0c27357 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -73,6 +73,7 @@ native <methods>; -keep class org.futo.circles.core.model.ShareUrlTypeArg -keep class org.futo.circles.model.PeopleCategoryTypeArg -keep class org.futo.circles.auth.model.ServerDomainArg +-keep class org.futo.circles.core.model.SelectRoomTypeArg -keepattributes SourceFile,LineNumberTable # Keep file names and line numbers. -keep public class * extends java.lang.Exception # Optional: Keep custom exceptions. diff --git a/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt b/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt index 50f6bef1297ae932052a33622136d5d1fcd84000..f6fdb43f346a565776457eb5a94e3d83f7cf13ab 100644 --- a/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt +++ b/app/src/main/java/org/futo/circles/feature/circles/accept_invite/AcceptCircleInviteDialogFragment.kt @@ -7,18 +7,18 @@ import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController import dagger.hilt.android.AndroidEntryPoint import org.futo.circles.R -import org.futo.circles.core.feature.room.select.interfaces.RoomsListener import org.futo.circles.core.base.fragment.BaseFullscreenDialogFragment import org.futo.circles.core.base.fragment.HasLoadingState import org.futo.circles.core.extensions.navigateSafe import org.futo.circles.core.extensions.observeResponse import org.futo.circles.core.extensions.onBackPressed import org.futo.circles.core.extensions.setIsVisible +import org.futo.circles.core.feature.room.select.SelectRoomsFragment +import org.futo.circles.core.feature.room.select.interfaces.RoomsListener import org.futo.circles.core.feature.room.select.interfaces.SelectRoomsListener -import org.futo.circles.core.model.CircleRoomTypeArg +import org.futo.circles.core.model.SelectRoomTypeArg import org.futo.circles.core.model.SelectableRoomListItem import org.futo.circles.databinding.DialogFragmentAcceptCircleInviteBinding -import org.futo.circles.core.feature.room.select.SelectRoomsFragment @AndroidEntryPoint class AcceptCircleInviteDialogFragment : @@ -29,7 +29,7 @@ class AcceptCircleInviteDialogFragment : override val fragment: Fragment = this private val viewModel by viewModels<AcceptCircleInviteViewModel>() - private val selectRoomsFragment by lazy { SelectRoomsFragment.create(CircleRoomTypeArg.Circle) } + private val selectRoomsFragment by lazy { SelectRoomsFragment.create(SelectRoomTypeArg.CirclesJoined) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt b/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt index 84e562f15e06829db335b3544beb838efb406bf7..57d16e470a42f56a3fb4051e8777c4c1015040bf 100644 --- a/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt +++ b/app/src/main/java/org/futo/circles/feature/share/circle/ShareWithCircleActivity.kt @@ -2,11 +2,11 @@ package org.futo.circles.feature.share.circle import dagger.hilt.android.AndroidEntryPoint import org.futo.circles.R +import org.futo.circles.core.feature.room.select.SelectRoomsFragment import org.futo.circles.core.feature.room.select.interfaces.RoomsPicker import org.futo.circles.core.feature.share.BaseShareActivity -import org.futo.circles.core.model.CircleRoomTypeArg +import org.futo.circles.core.model.SelectRoomTypeArg import org.futo.circles.core.utils.getTimelineRoomFor -import org.futo.circles.core.feature.room.select.SelectRoomsFragment @AndroidEntryPoint class ShareWithCircleActivity : BaseShareActivity() { @@ -14,7 +14,7 @@ class ShareWithCircleActivity : BaseShareActivity() { override val titleResId: Int = R.string.share_with_circle override val roomsPicker: RoomsPicker = - SelectRoomsFragment.create(CircleRoomTypeArg.Circle) + SelectRoomsFragment.create(SelectRoomTypeArg.CirclesJoined) override fun getShareRoomsIds(): List<String> = roomsPicker.getSelectedRooms().mapNotNull { getTimelineRoomFor(it.id)?.roomId } diff --git a/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt b/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt index 41fee17a76f6e2060415e3bd67f250e718c08a62..2e386653fb7cc9f7e4933e1f658aefc22bcac7db 100644 --- a/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt +++ b/app/src/main/java/org/futo/circles/feature/share/group/ShareWithGroupActivity.kt @@ -2,17 +2,18 @@ package org.futo.circles.feature.share.group import dagger.hilt.android.AndroidEntryPoint import org.futo.circles.R +import org.futo.circles.core.feature.room.select.SelectRoomsFragment import org.futo.circles.core.feature.room.select.interfaces.RoomsPicker import org.futo.circles.core.feature.share.BaseShareActivity -import org.futo.circles.core.model.CircleRoomTypeArg -import org.futo.circles.core.feature.room.select.SelectRoomsFragment +import org.futo.circles.core.model.SelectRoomTypeArg @AndroidEntryPoint class ShareWithGroupActivity : BaseShareActivity() { override val titleResId: Int = R.string.share_with_group - override val roomsPicker: RoomsPicker = SelectRoomsFragment.create(CircleRoomTypeArg.Group) + override val roomsPicker: RoomsPicker = + SelectRoomsFragment.create(SelectRoomTypeArg.GroupsJoined) override fun getShareRoomsIds(): List<String> = roomsPicker.getSelectedRooms().map { it.id } diff --git a/core/src/main/java/org/futo/circles/core/feature/invite_to_follow/InviteToFollowMeDialogFragment.kt b/core/src/main/java/org/futo/circles/core/feature/invite_to_follow/InviteToFollowMeDialogFragment.kt index e35f2c3b807dc7b47a57d0da7bf96da565e06ebe..9d016a4d374e3f71365708fffe91e63823ef506e 100644 --- a/core/src/main/java/org/futo/circles/core/feature/invite_to_follow/InviteToFollowMeDialogFragment.kt +++ b/core/src/main/java/org/futo/circles/core/feature/invite_to_follow/InviteToFollowMeDialogFragment.kt @@ -20,7 +20,7 @@ import org.futo.circles.core.extensions.showSuccess import org.futo.circles.core.feature.room.select.SelectRoomsFragment import org.futo.circles.core.feature.room.select.interfaces.RoomsListener import org.futo.circles.core.feature.room.select.interfaces.SelectRoomsListener -import org.futo.circles.core.model.CircleRoomTypeArg +import org.futo.circles.core.model.SelectRoomTypeArg import org.futo.circles.core.model.SelectableRoomListItem @AndroidEntryPoint @@ -33,7 +33,9 @@ class InviteToFollowMeDialogFragment : private val args: InviteToFollowMeDialogFragmentArgs by navArgs() private val viewModel by viewModels<InviteToFollowMeViewModel>() - private val selectRoomsFragment by lazy { SelectRoomsFragment.create(CircleRoomTypeArg.Circle) } + private val selectRoomsFragment by lazy { + SelectRoomsFragment.create(SelectRoomTypeArg.MyCircleNotJoinedByUser, args.userId) + } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsDataSource.kt b/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsDataSource.kt index ad184af93c54ca08d72e601cadc4539f55644775..6461cede00c2d3ea84113ffc485ae5e157ebc2be 100644 --- a/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsDataSource.kt +++ b/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsDataSource.kt @@ -13,11 +13,12 @@ import kotlinx.coroutines.flow.flowOn import org.futo.circles.core.extensions.getOrThrow import org.futo.circles.core.feature.workspace.SpacesTreeAccountDataSource import org.futo.circles.core.mapping.toSelectableRoomListItem -import org.futo.circles.core.model.CircleRoomTypeArg +import org.futo.circles.core.model.SelectRoomTypeArg import org.futo.circles.core.model.SelectableRoomListItem import org.futo.circles.core.utils.getGalleriesLiveData import org.futo.circles.core.utils.getGroupsLiveData import org.futo.circles.core.utils.getSpacesLiveData +import org.futo.circles.core.utils.getTimelineRoomFor import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject @@ -29,9 +30,11 @@ class SelectRoomsDataSource @Inject constructor( ) { private val ordinal = savedStateHandle.getOrThrow<Int>(SelectRoomsFragment.TYPE_ORDINAL) - private val roomType: CircleRoomTypeArg = - CircleRoomTypeArg.entries.firstOrNull { it.ordinal == ordinal } - ?: CircleRoomTypeArg.Circle + private val roomType: SelectRoomTypeArg = + SelectRoomTypeArg.entries.firstOrNull { it.ordinal == ordinal } + ?: SelectRoomTypeArg.CirclesJoined + + private val filterUserId: String? = savedStateHandle[SelectRoomsFragment.USER_ID] private val selectedRoomsFlow = MutableStateFlow<List<SelectableRoomListItem>>(emptyList()) val roomsFlow = getMergedRoomsListFlow() @@ -47,16 +50,17 @@ class SelectRoomsDataSource @Inject constructor( }.flowOn(Dispatchers.IO).distinctUntilChanged() private fun getRoomsFlowWithType(): Flow<List<RoomSummary>> = when (roomType) { - CircleRoomTypeArg.Circle -> getSpacesLiveData(listOf(Membership.JOIN)).map { summaries -> - val joinedCirclesIds = spacesTreeAccountDataSource.getJoinedCirclesIds() - summaries.mapNotNull { summary -> - if (joinedCirclesIds.contains(summary.roomId)) summary - else null - } + SelectRoomTypeArg.CirclesJoined -> getSpacesLiveData(listOf(Membership.JOIN)).map { summaries -> + filterAllMyCirclesRoomSummaries(summaries) }.asFlow() - CircleRoomTypeArg.Group -> getGroupsLiveData(listOf(Membership.JOIN)).asFlow() - CircleRoomTypeArg.Photo -> getGalleriesLiveData(listOf(Membership.JOIN)).asFlow() + SelectRoomTypeArg.MyCircleNotJoinedByUser -> getSpacesLiveData(listOf(Membership.JOIN)).map { summaries -> + filterAllMyCirclesRoomSummaries(summaries).filter { !isUserJoinedToCircle(it) } + }.asFlow() + + SelectRoomTypeArg.GroupsJoined -> getGroupsLiveData(listOf(Membership.JOIN)).asFlow() + + SelectRoomTypeArg.PhotosJoined -> getGalleriesLiveData(listOf(Membership.JOIN)).asFlow() } fun getSelectedRooms() = selectedRoomsFlow.value.filter { it.isSelected } @@ -68,6 +72,20 @@ class SelectRoomsDataSource @Inject constructor( selectedRoomsFlow.value = list } + private fun filterAllMyCirclesRoomSummaries(allJoinedSpacesSummaries: List<RoomSummary>): List<RoomSummary> { + val joinedCirclesIds = spacesTreeAccountDataSource.getJoinedCirclesIds() + return allJoinedSpacesSummaries.mapNotNull { summary -> + if (joinedCirclesIds.contains(summary.roomId)) summary + else null + } + } + + private fun isUserJoinedToCircle(circleSpaceSummary: RoomSummary): Boolean { + val timeline = getTimelineRoomFor(circleSpaceSummary.roomId) + val member = timeline?.membershipService()?.getRoomMember(filterUserId ?: "") + return member?.membership == Membership.JOIN + } + private fun List<SelectableRoomListItem>.containsWithId(id: String) = firstOrNull { it.id == id } != null } \ No newline at end of file diff --git a/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsFragment.kt b/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsFragment.kt index b111ed43adc51965b1d307cf11420da39a813c43..192ec0202d8679ae525c0d642d86c0a5d557abad 100644 --- a/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsFragment.kt +++ b/core/src/main/java/org/futo/circles/core/feature/room/select/SelectRoomsFragment.kt @@ -11,12 +11,12 @@ import org.futo.circles.core.base.fragment.BaseBindingFragment import org.futo.circles.core.databinding.FragmentSelectRoomsBinding import org.futo.circles.core.extensions.observeData import org.futo.circles.core.extensions.setIsVisible -import org.futo.circles.core.model.CircleRoomTypeArg -import org.futo.circles.core.feature.room.select.list.SelectRoomsAdapter -import org.futo.circles.core.feature.room.select.list.SelectedChipsRoomsAdapter import org.futo.circles.core.feature.room.select.interfaces.RoomsListener import org.futo.circles.core.feature.room.select.interfaces.RoomsPicker import org.futo.circles.core.feature.room.select.interfaces.SelectRoomsListener +import org.futo.circles.core.feature.room.select.list.SelectRoomsAdapter +import org.futo.circles.core.feature.room.select.list.SelectedChipsRoomsAdapter +import org.futo.circles.core.model.SelectRoomTypeArg @AndroidEntryPoint class SelectRoomsFragment : @@ -70,8 +70,13 @@ class SelectRoomsFragment : companion object { const val TYPE_ORDINAL = "type_ordinal" - fun create(roomType: CircleRoomTypeArg) = SelectRoomsFragment().apply { - arguments = bundleOf(TYPE_ORDINAL to roomType.ordinal) - } + const val USER_ID = "userId" + fun create(roomType: SelectRoomTypeArg, userId: String? = null) = + SelectRoomsFragment().apply { + arguments = bundleOf( + TYPE_ORDINAL to roomType.ordinal, + USER_ID to userId + ) + } } } \ No newline at end of file diff --git a/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt b/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt index 76772f3e0922aba57324ac9b02bba3bf9063af79..166497ae605203ce6eee138f421a4333438498a0 100644 --- a/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt +++ b/core/src/main/java/org/futo/circles/core/mapping/RoomSummaryMapping.kt @@ -6,7 +6,9 @@ import org.futo.circles.core.extensions.notEmptyDisplayName import org.futo.circles.core.model.CircleRoomTypeArg import org.futo.circles.core.model.JoinedGalleryListItem import org.futo.circles.core.model.RoomInfo +import org.futo.circles.core.model.SelectRoomTypeArg import org.futo.circles.core.model.SelectableRoomListItem +import org.futo.circles.core.model.isCircle import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.user.model.User @@ -15,13 +17,13 @@ fun RoomSummary.nameOrId() = displayName.takeIf { it.isNotEmpty() } ?: name.takeIf { it.isNotEmpty() } ?: roomId fun RoomSummary.toSelectableRoomListItem( - roomTypeArg: CircleRoomTypeArg, + roomTypeArg: SelectRoomTypeArg, selected: Boolean = false ) = SelectableRoomListItem( id = roomId, info = RoomInfo( nameOrId(), - if (roomTypeArg == CircleRoomTypeArg.Circle) getCircleAvatarUrl() else avatarUrl + if (roomTypeArg.isCircle()) getCircleAvatarUrl() else avatarUrl ), isSelected = selected ) diff --git a/core/src/main/java/org/futo/circles/core/model/SelectRoomTypeArg.kt b/core/src/main/java/org/futo/circles/core/model/SelectRoomTypeArg.kt new file mode 100644 index 0000000000000000000000000000000000000000..d936a220f84e988ebd665808d1c9c15a69f83d4e --- /dev/null +++ b/core/src/main/java/org/futo/circles/core/model/SelectRoomTypeArg.kt @@ -0,0 +1,11 @@ +package org.futo.circles.core.model + +enum class SelectRoomTypeArg { + CirclesJoined, + GroupsJoined, + PhotosJoined, + MyCircleNotJoinedByUser +} + +fun SelectRoomTypeArg.isCircle() = + this == SelectRoomTypeArg.CirclesJoined || this == SelectRoomTypeArg.MyCircleNotJoinedByUser \ No newline at end of file diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt index e12de59d4429c4816789a2cf36a78c4347b217ce..2091288ae9df91c2a75edfcbef0fa84e8b02c9de 100644 --- a/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt +++ b/gallery/src/main/java/org/futo/circles/gallery/feature/select/SelectGalleriesDataSource.kt @@ -2,7 +2,7 @@ package org.futo.circles.gallery.feature.select import androidx.lifecycle.MutableLiveData import org.futo.circles.core.mapping.toSelectableRoomListItem -import org.futo.circles.core.model.CircleRoomTypeArg +import org.futo.circles.core.model.SelectRoomTypeArg import org.futo.circles.core.model.SelectableRoomListItem import org.futo.circles.core.utils.getGalleries import org.matrix.android.sdk.api.session.room.model.Membership @@ -14,7 +14,7 @@ class SelectGalleriesDataSource @Inject constructor() { private fun getInitialGalleriesList(): List<SelectableRoomListItem> = getGalleries(membershipFilter = listOf(Membership.JOIN)).map { - it.toSelectableRoomListItem(CircleRoomTypeArg.Photo) + it.toSelectableRoomListItem(SelectRoomTypeArg.PhotosJoined) } fun toggleGallerySelect(gallery: SelectableRoomListItem) {