diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt index c81654a9f1..1620941ece 100644 --- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt +++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt @@ -922,4 +922,23 @@ class BlockDataRepository( identity = identity ) } + + override suspend fun removeSpaceMembers(space: SpaceId, identities: List) { + remote.removeSpaceMembers( + space = space, + identities = identities + ) + } + + override suspend fun changeSpaceMemberPermissions( + space: SpaceId, + identity: Id, + permission: ParticipantPermissions + ) { + remote.changeSpaceMemberPermissions( + space = space, + identity = identity, + permission = permission + ) + } } \ No newline at end of file diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt index 906163448f..0b1e352bb3 100644 --- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt +++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt @@ -391,8 +391,13 @@ interface BlockRemote { identity: Id, permissions: ParticipantPermissions ) - suspend fun declineSpaceRequest( + suspend fun declineSpaceRequest(space: SpaceId, identity: Id) + + suspend fun removeSpaceMembers(space: SpaceId, identities: List) + + suspend fun changeSpaceMemberPermissions( space: SpaceId, - identity: Id + identity: Id, + permission: ParticipantPermissions ) } \ No newline at end of file diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt b/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt index b588c44519..79d8ac24cb 100644 --- a/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt +++ b/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt @@ -437,8 +437,11 @@ interface BlockRepository { identity: Id, permissions: ParticipantPermissions ) - suspend fun declineSpaceRequest( + suspend fun declineSpaceRequest(space: SpaceId, identity: Id) + suspend fun removeSpaceMembers(space: SpaceId, identities: List) + suspend fun changeSpaceMemberPermissions( space: SpaceId, - identity: Id + identity: Id, + permission: ParticipantPermissions ) } \ No newline at end of file diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/ChangeSpaceMemberPermissions.kt b/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/ChangeSpaceMemberPermissions.kt new file mode 100644 index 0000000000..bbd1a0a728 --- /dev/null +++ b/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/ChangeSpaceMemberPermissions.kt @@ -0,0 +1,29 @@ +package com.anytypeio.anytype.domain.multiplayer + +import com.anytypeio.anytype.core_models.Id +import com.anytypeio.anytype.core_models.multiplayer.ParticipantPermissions +import com.anytypeio.anytype.core_models.primitives.SpaceId +import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers +import com.anytypeio.anytype.domain.base.ResultInteractor +import com.anytypeio.anytype.domain.block.repo.BlockRepository +import javax.inject.Inject + +class ChangeSpaceMemberPermissions @Inject constructor( + private val repo: BlockRepository, + dispatchers: AppCoroutineDispatchers +) : ResultInteractor(dispatchers.io) { + + override suspend fun doWork(params: Params) { + repo.changeSpaceMemberPermissions( + space = params.space, + identity = params.identity, + permission = params.permission + ) + } + + data class Params( + val space: SpaceId, + val identity: Id, + val permission: ParticipantPermissions + ) +} \ No newline at end of file diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/RemoveSpaceMembers.kt b/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/RemoveSpaceMembers.kt new file mode 100644 index 0000000000..1d929b76a2 --- /dev/null +++ b/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/RemoveSpaceMembers.kt @@ -0,0 +1,26 @@ +package com.anytypeio.anytype.domain.multiplayer + +import com.anytypeio.anytype.core_models.Id +import com.anytypeio.anytype.core_models.primitives.SpaceId +import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers +import com.anytypeio.anytype.domain.base.ResultInteractor +import com.anytypeio.anytype.domain.block.repo.BlockRepository +import javax.inject.Inject + +class RemoveSpaceMembers @Inject constructor( + private val repo: BlockRepository, + dispatchers: AppCoroutineDispatchers +): ResultInteractor(dispatchers.io) { + + override suspend fun doWork(params: Params) { + repo.removeSpaceMembers( + space = params.space, + identities = params.identities + ) + } + + /** + * @property [identities] identities of members of a given space + */ + data class Params(val space: SpaceId, val identities: List) +} \ No newline at end of file diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt index fa810f65d8..1cf916861a 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt @@ -884,4 +884,23 @@ class BlockMiddleware( identity = identity ) } + + override suspend fun removeSpaceMembers(space: SpaceId, identities: List) { + middleware.removeSpaceMembers( + space = space, + identities = identities + ) + } + + override suspend fun changeSpaceMemberPermissions( + space: SpaceId, + identity: Id, + permission: ParticipantPermissions + ) { + middleware.changeSpaceMemberPermissions( + space = space, + identity = identity, + permission = permission + ) + } } \ No newline at end of file diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt index 421bc807a7..62e32c5ceb 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt @@ -2,6 +2,7 @@ package com.anytypeio.anytype.middleware.interactor import anytype.Rpc import anytype.model.Block +import anytype.model.ParticipantPermissionChange import anytype.model.Range import com.anytypeio.anytype.core_models.AccountSetup import com.anytypeio.anytype.core_models.AccountStatus @@ -2413,6 +2414,36 @@ class Middleware @Inject constructor( if (BuildConfig.DEBUG) logResponse(response) } + @Throws(Exception::class) + fun removeSpaceMembers( + space: SpaceId, + identities: List + ) { + val request = Rpc.Space.ParticipantRemove.Request( + spaceId = space.id, + identities = identities + ) + if (BuildConfig.DEBUG) logRequest(request) + val response = service.spaceParticipantRemove(request) + if (BuildConfig.DEBUG) logResponse(response) + } + + @Throws(Exception::class) + fun changeSpaceMemberPermissions(space: SpaceId, identity: Id, permission: ParticipantPermissions) { + val request = Rpc.Space.ParticipantPermissionsChange.Request( + spaceId = space.id, + changes = listOf( + ParticipantPermissionChange( + identity = identity, + perms = permission.toMw() + ) + ) + ) + if (BuildConfig.DEBUG) logRequest(request) + val response = service.spaceParticipantPermissionsChange(request) + if (BuildConfig.DEBUG) logResponse(response) + } + private fun logRequest(any: Any) { logger.logRequest(any).also { if (BuildConfig.DEBUG && threadInfo.isOnMainThread()) { diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/multiplayer/ShareSpaceViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/multiplayer/ShareSpaceViewModel.kt index f3219ae908..a12bc3a2ec 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/multiplayer/ShareSpaceViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/multiplayer/ShareSpaceViewModel.kt @@ -8,10 +8,13 @@ import com.anytypeio.anytype.core_models.ObjectWrapper import com.anytypeio.anytype.core_models.multiplayer.ParticipantPermissions import com.anytypeio.anytype.core_models.multiplayer.ParticipantStatus import com.anytypeio.anytype.core_models.primitives.SpaceId +import com.anytypeio.anytype.core_utils.ext.msg import com.anytypeio.anytype.domain.base.fold import com.anytypeio.anytype.domain.library.StoreSearchParams import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer +import com.anytypeio.anytype.domain.multiplayer.ChangeSpaceMemberPermissions import com.anytypeio.anytype.domain.multiplayer.GenerateSpaceInviteLink +import com.anytypeio.anytype.domain.multiplayer.RemoveSpaceMembers import com.anytypeio.anytype.presentation.common.BaseViewModel import com.anytypeio.anytype.presentation.search.ObjectSearchConstants import javax.inject.Inject @@ -24,6 +27,8 @@ import timber.log.Timber class ShareSpaceViewModel( private val params: Params, private val generateSpaceInviteLink: GenerateSpaceInviteLink, + private val removeSpaceMembers: RemoveSpaceMembers, + private val changeSpaceMemberPermissions: ChangeSpaceMemberPermissions, private val container: StorelessSubscriptionContainer ) : BaseViewModel() { @@ -98,7 +103,70 @@ class ShareSpaceViewModel( } fun onApproveUnjoinRequestClicked(view: ShareSpaceMemberView) { + // TODO + } + fun onCanEditClicked( + view: ShareSpaceMemberView + ) { + viewModelScope.launch { + if (view.config != ShareSpaceMemberView.Config.Member.Reader) { + changeSpaceMemberPermissions.async( + ChangeSpaceMemberPermissions.Params( + space = params.space, + identity = view.obj.identity, + permission = ParticipantPermissions.WRITER + ) + ).fold( + onFailure = { e -> + Timber.e(e, "Error while changing member permissions").also { + sendToast(e.msg()) + } + } + ) + } + } + } + + fun onCanReadClicked( + view: ShareSpaceMemberView + ) { + viewModelScope.launch { + if (view.config != ShareSpaceMemberView.Config.Member.Reader) { + changeSpaceMemberPermissions.async( + ChangeSpaceMemberPermissions.Params( + space = params.space, + identity = view.obj.identity, + permission = ParticipantPermissions.READER + ) + ).fold( + onFailure = { e -> + Timber.e(e, "Error while changing member permissions").also { + sendToast(e.msg()) + } + } + ) + } + } + } + + fun onRemoveMemberClicked( + view: ShareSpaceMemberView + ) { + viewModelScope.launch { + removeSpaceMembers.async( + RemoveSpaceMembers.Params( + space = params.space, + identities = listOf(view.obj.identity) + ) + ).fold( + onFailure = { e -> + Timber.e(e, "Error while removing space member").also { + sendToast(e.msg()) + } + } + ) + } } override fun onCleared() { @@ -111,12 +179,16 @@ class ShareSpaceViewModel( class Factory @Inject constructor( private val params: Params, private val generateSpaceInviteLink: GenerateSpaceInviteLink, + private val changeSpaceMemberPermissions: ChangeSpaceMemberPermissions, + private val removeSpaceMembers: RemoveSpaceMembers, private val container: StorelessSubscriptionContainer ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = ShareSpaceViewModel( params = params, generateSpaceInviteLink = generateSpaceInviteLink, + changeSpaceMemberPermissions = changeSpaceMemberPermissions, + removeSpaceMembers = removeSpaceMembers, container = container ) as T }