1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-2258 Multiplayer | Enhancement | UX and API for the request-to-join-space flow (#946)

This commit is contained in:
Evgenii Kozlov 2024-02-28 22:05:01 +01:00 committed by GitHub
parent ccc23c62d6
commit eb64b68503
Signed by: github
GPG key ID: B5690EEEBB952194
13 changed files with 528 additions and 64 deletions

View file

@ -63,6 +63,7 @@ import com.anytypeio.anytype.di.feature.cover.UnsplashModule
import com.anytypeio.anytype.di.feature.home.DaggerHomeScreenComponent
import com.anytypeio.anytype.di.feature.library.DaggerLibraryComponent
import com.anytypeio.anytype.di.feature.multiplayer.DaggerShareSpaceComponent
import com.anytypeio.anytype.di.feature.multiplayer.DaggerSpaceJoinRequestComponent
import com.anytypeio.anytype.di.feature.objects.DaggerSelectObjectTypeComponent
import com.anytypeio.anytype.di.feature.onboarding.DaggerOnboardingComponent
import com.anytypeio.anytype.di.feature.onboarding.DaggerOnboardingStartComponent
@ -104,6 +105,7 @@ import com.anytypeio.anytype.di.feature.widgets.SelectWidgetSourceModule
import com.anytypeio.anytype.di.feature.widgets.SelectWidgetTypeModule
import com.anytypeio.anytype.di.main.MainComponent
import com.anytypeio.anytype.presentation.multiplayer.ShareSpaceViewModel
import com.anytypeio.anytype.presentation.multiplayer.SpaceJoinRequestViewModel
import com.anytypeio.anytype.presentation.objects.SelectObjectTypeViewModel
import com.anytypeio.anytype.presentation.relations.option.CreateOrEditOptionViewModel
import com.anytypeio.anytype.presentation.relations.value.attachment.AttachmentValueViewModel
@ -1047,6 +1049,14 @@ class ComponentManager(
.build()
}
val spaceJoinRequestComponent = ComponentWithParams { params: SpaceJoinRequestViewModel.Params ->
DaggerSpaceJoinRequestComponent
.builder()
.withDependencies(findComponentDependencies())
.withParams(params = params)
.build()
}
class Component<T>(private val builder: () -> T) {
private var instance: T? = null

View file

@ -0,0 +1,56 @@
package com.anytypeio.anytype.di.feature.multiplayer
import androidx.lifecycle.ViewModelProvider
import com.anytypeio.anytype.core_utils.di.scope.PerDialog
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.multiplayer.SpaceJoinRequestViewModel
import com.anytypeio.anytype.ui.multiplayer.SpaceJoinRequestFragment
import dagger.Binds
import dagger.BindsInstance
import dagger.Component
import dagger.Module
@Component(
dependencies = [SpaceJoinRequestDependencies::class],
modules = [
SpaceJoinRequestModule::class,
SpaceJoinRequestModule.Declarations::class
]
)
@PerDialog
interface SpaceJoinRequestComponent {
@Component.Builder
interface Builder {
fun withDependencies(dependencies: SpaceJoinRequestDependencies): Builder
@BindsInstance
fun withParams(params: SpaceJoinRequestViewModel.Params): Builder
fun build(): SpaceJoinRequestComponent
}
fun inject(fragment: SpaceJoinRequestFragment)
}
@Module
object SpaceJoinRequestModule {
@Module
interface Declarations {
@PerScreen
@Binds
fun bindViewModelFactory(factory: SpaceJoinRequestViewModel.Factory): ViewModelProvider.Factory
}
}
interface SpaceJoinRequestDependencies : ComponentDependencies {
fun blockRepository(): BlockRepository
fun urlBuilder(): UrlBuilder
fun dispatchers(): AppCoroutineDispatchers
fun spaceManager(): SpaceManager
}

View file

@ -22,6 +22,7 @@ import com.anytypeio.anytype.di.feature.auth.DeletedAccountDependencies
import com.anytypeio.anytype.di.feature.home.HomeScreenDependencies
import com.anytypeio.anytype.di.feature.library.LibraryDependencies
import com.anytypeio.anytype.di.feature.multiplayer.ShareSpaceDependencies
import com.anytypeio.anytype.di.feature.multiplayer.SpaceJoinRequestDependencies
import com.anytypeio.anytype.di.feature.objects.SelectObjectTypeDependencies
import com.anytypeio.anytype.di.feature.onboarding.OnboardingDependencies
import com.anytypeio.anytype.di.feature.onboarding.OnboardingStartDependencies
@ -106,7 +107,9 @@ interface MainComponent :
SpacesStorageDependencies,
AppPreferencesDependencies,
AddToAnytypeDependencies,
ShareSpaceDependencies {
ShareSpaceDependencies,
SpaceJoinRequestDependencies
{
fun inject(app: AndroidApplication)
@ -286,4 +289,9 @@ private abstract class ComponentDependenciesModule private constructor() {
@IntoMap
@ComponentDependenciesKey(ShareSpaceDependencies::class)
abstract fun provideShareSpaceDependencies(component: MainComponent): ComponentDependencies
@Binds
@IntoMap
@ComponentDependenciesKey(SpaceJoinRequestDependencies::class)
abstract fun provideSpaceJoinRequestDependencies(component: MainComponent): ComponentDependencies
}

View file

@ -12,6 +12,8 @@ import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.core.os.bundleOf
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.fragment.findNavController
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_ui.features.multiplayer.ShareSpaceScreen
import com.anytypeio.anytype.core_utils.ext.arg
@ -45,16 +47,18 @@ class ShareSpaceFragment : BaseBottomSheetComposeFragment() {
onRegenerateInviteLinkClicked = vm::onRegenerateInviteLinkClicked,
onShareInviteLinkClicked = vm::onShareInviteLinkClicked,
members = vm.members.collectAsStateWithLifecycle().value,
onRequestAction = {
toast("TODO")
}
onViewRequestClicked = vm::onViewRequestClicked,
onApproveUnjoinRequestClicked = vm::onApproveUnjoinRequestClicked
)
LaunchedEffect(Unit) {
vm.commands.collect { command ->
proceedWithCommand(command)
}
}
LaunchedEffect(Unit) {
vm.commands.collect { command ->
proceedWithCommand(command)
}
}
LaunchedEffect(Unit) {
vm.toasts.collect { toast(it) }
}
}
}
}
@ -75,6 +79,15 @@ class ShareSpaceFragment : BaseBottomSheetComposeFragment() {
}
startActivity(Intent.createChooser(intent, null))
}
is ShareSpaceViewModel.Command.ViewJoinRequest -> {
findNavController().navigate(
resId = R.id.spaceJoinRequestScreen,
args = SpaceJoinRequestFragment.args(
space = command.space,
member = command.member
)
)
}
}
}

View file

@ -0,0 +1,93 @@
package com.anytypeio.anytype.ui.multiplayer
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.core.os.bundleOf
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_ui.features.multiplayer.SpaceJoinRequestScreen
import com.anytypeio.anytype.core_utils.ext.arg
import com.anytypeio.anytype.core_utils.ext.toast
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
import com.anytypeio.anytype.di.common.componentManager
import com.anytypeio.anytype.presentation.multiplayer.SpaceJoinRequestViewModel
import com.anytypeio.anytype.ui.settings.typography
import javax.inject.Inject
class SpaceJoinRequestFragment : BaseBottomSheetComposeFragment() {
private val space get() = arg<Id>(SPACE_ID_KEY)
private val member get() = arg<Id>(MEMBER_ID_KEY)
@Inject
lateinit var factory: SpaceJoinRequestViewModel.Factory
private val vm by viewModels<SpaceJoinRequestViewModel> { factory }
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return ComposeView(requireContext()).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
MaterialTheme(typography = typography) {
when(val state = vm.viewState.collectAsStateWithLifecycle().value) {
SpaceJoinRequestViewModel.ViewState.Error -> {
// TODO Send toast.
}
SpaceJoinRequestViewModel.ViewState.Init -> {
// Draw nothing.
}
is SpaceJoinRequestViewModel.ViewState.Success -> {
SpaceJoinRequestScreen(
state = state,
onAddViewerClicked = vm::onJoinAsReaderClicked,
onAddEditorClicked = vm::onJoinAsEditorClicked,
onRejectClicked = vm::onRejectRequestClicked
)
}
}
LaunchedEffect(Unit) {
vm.toasts.collect { toast(it) }
}
}
}
}
}
override fun injectDependencies() {
componentManager().spaceJoinRequestComponent.get(
SpaceJoinRequestViewModel.Params(
space = SpaceId(
space
), member = member
)
).inject(fragment = this)
}
override fun releaseDependencies() {
componentManager().spaceJoinRequestComponent.release()
}
companion object {
const val SPACE_ID_KEY = "arg.space-join-request.space-id-key"
const val MEMBER_ID_KEY = "arg.space-join-request.member-id-key"
fun args(
space: SpaceId,
member: Id
): Bundle = bundleOf(
SPACE_ID_KEY to space.id,
MEMBER_ID_KEY to member
)
}
}

View file

@ -538,4 +538,8 @@
android:id="@+id/shareSpaceScreen"
android:name="com.anytypeio.anytype.ui.multiplayer.ShareSpaceFragment"/>
<dialog
android:id="@+id/spaceJoinRequestScreen"
android:name="com.anytypeio.anytype.ui.multiplayer.SpaceJoinRequestFragment"/>
</navigation>

View file

@ -317,6 +317,7 @@ sealed class ObjectWrapper {
private val default = map.withDefault { null }
val id: Id by default
val identity: Id by default
val name: String? by default
val status

View file

@ -32,7 +32,7 @@ import com.anytypeio.anytype.core_ui.views.ButtonSecondary
import com.anytypeio.anytype.core_ui.views.ButtonSize
import com.anytypeio.anytype.core_ui.views.ButtonWarning
import com.anytypeio.anytype.core_ui.views.HeadlineHeading
import com.anytypeio.anytype.presentation.multiplayer.SpaceJoinRequestView
import com.anytypeio.anytype.presentation.multiplayer.SpaceJoinRequestViewModel.ViewState
@Preview
@Composable
@ -41,17 +41,16 @@ fun SpaceJoinRequestScreenPreview() {
onAddEditorClicked = {},
onAddViewerClicked = {},
onRejectClicked = {},
spaceJoinRequestView = SpaceJoinRequestView(
state = ViewState.Success(
memberName = "Merk",
spaceName = "Investors",
comment = "Hi Zhanna. Its Merk, you sent me the link. Have a great day."
spaceName = "Investors"
)
)
}
@Composable
fun SpaceJoinRequestScreen(
spaceJoinRequestView: SpaceJoinRequestView,
state: ViewState.Success,
onAddViewerClicked: () -> Unit,
onAddEditorClicked: () -> Unit,
onRejectClicked: () -> Unit,
@ -81,8 +80,8 @@ fun SpaceJoinRequestScreen(
Text(
text = stringResource(
R.string.multiplayer_space_join_request_header,
spaceJoinRequestView.memberName,
spaceJoinRequestView.spaceName
state.memberName,
state.spaceName
),
style = HeadlineHeading,
textAlign = TextAlign.Center,
@ -91,36 +90,7 @@ fun SpaceJoinRequestScreen(
),
color = colorResource(id = R.color.text_primary)
)
Spacer(modifier = Modifier.height(12.dp))
Box(
modifier = Modifier
.height(IntrinsicSize.Min)
.padding(start = 20.dp, end = 20.dp)
.background(
color = colorResource(id = R.color.shape_tertiary),
shape = RoundedCornerShape(4.dp)
)
) {
Text(
text = spaceJoinRequestView.comment,
style = BodyCalloutRegular,
color = colorResource(id = R.color.text_primary),
modifier = Modifier.padding(16.dp)
)
Box(
modifier = Modifier
.fillMaxHeight()
.width(4.dp)
.background(
color = colorResource(id = R.color.glyph_active),
shape = RoundedCornerShape(
topStart = 4.dp,
bottomStart = 4.dp
)
)
)
}
Spacer(modifier = Modifier.height(30.dp))
Spacer(modifier = Modifier.height(20.dp))
ButtonSecondary(
text = stringResource(R.string.multiplayer_space_add_viewer),
onClick = throttledClick(
@ -156,3 +126,35 @@ fun SpaceJoinRequestScreen(
Spacer(modifier = Modifier.height(16.dp))
}
}
@Composable
private fun CommentView() {
Box(
modifier = Modifier
.height(IntrinsicSize.Min)
.padding(start = 20.dp, end = 20.dp)
.background(
color = colorResource(id = R.color.shape_tertiary),
shape = RoundedCornerShape(4.dp)
)
) {
Text(
text = "",
style = BodyCalloutRegular,
color = colorResource(id = R.color.text_primary),
modifier = Modifier.padding(16.dp)
)
Box(
modifier = Modifier
.fillMaxHeight()
.width(4.dp)
.background(
color = colorResource(id = R.color.glyph_active),
shape = RoundedCornerShape(
topStart = 4.dp,
bottomStart = 4.dp
)
)
)
}
}

View file

@ -54,7 +54,8 @@ fun ShareSpaceScreen(
viewState: ShareSpaceViewModel.ViewState,
onRegenerateInviteLinkClicked: () -> Unit,
onShareInviteLinkClicked: () -> Unit,
onRequestAction: (ShareSpaceMemberView.Config.Request) -> Unit
onViewRequestClicked: (ShareSpaceMemberView) -> Unit,
onApproveUnjoinRequestClicked: (ShareSpaceMemberView) -> Unit
) {
Box(modifier = Modifier.fillMaxSize()) {
LazyColumn(modifier = Modifier.fillMaxSize()) {
@ -98,7 +99,12 @@ fun ShareSpaceScreen(
SpaceMemberRequest(
member = member.obj,
request = config,
onRequestAction = onRequestAction
onViewRequestClicked = {
onViewRequestClicked(member)
},
onApproveUnjoinRequestClicked = {
onApproveUnjoinRequestClicked(member)
}
)
}
}
@ -186,7 +192,8 @@ private fun SpaceMember(
private fun SpaceMemberRequest(
member: ObjectWrapper.Participant,
request: ShareSpaceMemberView.Config.Request,
onRequestAction: (ShareSpaceMemberView.Config.Request) -> Unit
onViewRequestClicked: () -> Unit,
onApproveUnjoinRequestClicked: () -> Unit
) {
Row(
modifier = Modifier
@ -245,7 +252,7 @@ private fun SpaceMemberRequest(
ButtonSecondary(
text = stringResource(R.string.multiplayer_view_request),
onClick = throttledClick(
onClick = { onRequestAction(request) }
onClick = { onViewRequestClicked() }
),
size = ButtonSize.Small,
modifier = Modifier.align(Alignment.CenterVertically)
@ -255,7 +262,7 @@ private fun SpaceMemberRequest(
ButtonSecondary(
text = stringResource(R.string.multiplayer_approve_request),
onClick = throttledClick(
onClick = { onRequestAction(request) }
onClick = { onApproveUnjoinRequestClicked() }
),
size = ButtonSize.Small,
modifier = Modifier.align(Alignment.CenterVertically)
@ -278,7 +285,8 @@ fun SpaceJoinRequestPreview() {
)
),
request = ShareSpaceMemberView.Config.Request.Join,
onRequestAction = {},
onApproveUnjoinRequestClicked = {},
onViewRequestClicked = {}
)
}
@ -294,7 +302,8 @@ fun SpaceUnjoinRequestPreview() {
)
),
request = ShareSpaceMemberView.Config.Request.Unjoin,
onRequestAction = {},
onApproveUnjoinRequestClicked = {},
onViewRequestClicked = {}
)
}
@ -307,7 +316,6 @@ fun ShareSpaceScreenPreview() {
),
onShareInviteLinkClicked = {},
onRegenerateInviteLinkClicked = {},
onRequestAction = {},
members = buildList {
add(
ShareSpaceMemberView(
@ -352,7 +360,9 @@ fun ShareSpaceScreenPreview() {
config = ShareSpaceMemberView.Config.Request.Join
)
)
}
},
onApproveUnjoinRequestClicked = {},
onViewRequestClicked = {}
)
}

View file

@ -7,8 +7,9 @@ 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 ApproveJoinSpaceRequest(
class ApproveJoinSpaceRequest @Inject constructor(
private val repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<ApproveJoinSpaceRequest.Params, Unit>(dispatchers.io) {

View file

@ -6,8 +6,9 @@ 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 DeclineSpaceJoinRequest(
class DeclineSpaceJoinRequest @Inject constructor(
private val repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<DeclineSpaceJoinRequest.Params, Unit>(dispatchers.io) {

View file

@ -3,6 +3,7 @@ package com.anytypeio.anytype.presentation.multiplayer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.multiplayer.ParticipantPermissions
import com.anytypeio.anytype.core_models.multiplayer.ParticipantStatus
@ -36,7 +37,7 @@ class ShareSpaceViewModel(
viewModelScope.launch {
container.subscribe(
StoreSearchParams(
subscription = this::class.java.toGenericString(),
subscription = SHARE_SPACE_SUBSCRIPTION,
filters = ObjectSearchConstants.filterParticipants(
spaces = listOf(params.space.id)
),
@ -85,6 +86,28 @@ class ShareSpaceViewModel(
}
}
fun onViewRequestClicked(view: ShareSpaceMemberView) {
viewModelScope.launch {
commands.emit(
Command.ViewJoinRequest(
space = params.space,
member = view.obj.id
)
)
}
}
fun onApproveUnjoinRequestClicked(view: ShareSpaceMemberView) {
}
override fun onCleared() {
viewModelScope.launch {
container.unsubscribe(subscriptions = listOf(SHARE_SPACE_SUBSCRIPTION))
}
super.onCleared()
}
class Factory @Inject constructor(
private val params: Params,
private val generateSpaceInviteLink: GenerateSpaceInviteLink,
@ -109,6 +132,11 @@ class ShareSpaceViewModel(
sealed class Command {
data class ShareInviteLink(val link: String) : Command()
data class ViewJoinRequest(val space: SpaceId, val member: Id) : Command()
}
companion object {
const val SHARE_SPACE_SUBSCRIPTION = "share-space-subscription"
}
}
@ -169,10 +197,4 @@ data class ShareSpaceMemberView(
}
}
}
}
data class SpaceJoinRequestView(
val memberName: String,
val spaceName: String,
val comment: String
)
}

View file

@ -0,0 +1,243 @@
package com.anytypeio.anytype.presentation.multiplayer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVFilterCondition
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.multiplayer.ParticipantPermissions
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.multiplayer.ApproveJoinSpaceRequest
import com.anytypeio.anytype.domain.multiplayer.DeclineSpaceJoinRequest
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.common.ViewState
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import timber.log.Timber
class SpaceJoinRequestViewModel(
private val params: Params,
private val approveJoinSpaceRequest: ApproveJoinSpaceRequest,
private val declineSpaceJoinRequest: DeclineSpaceJoinRequest,
private val searchObjects: SearchObjects,
private val spaceManager: SpaceManager
): BaseViewModel() {
val isDismissed = MutableStateFlow(false)
private val state = MutableStateFlow<State>(State.Init)
val viewState = MutableStateFlow<ViewState>(ViewState.Init)
init {
viewModelScope.launch {
val config = spaceManager.getConfig()
if (config != null && config.space == params.space.id) {
searchObjects(
SearchObjects.Params(
sorts = emptyList(),
filters = buildList {
add(
DVFilter(
relation = Relations.IS_ARCHIVED,
condition = DVFilterCondition.NOT_EQUAL,
value = true
)
)
add(
DVFilter(
relation = Relations.IS_DELETED,
condition = DVFilterCondition.NOT_EQUAL,
value = true
)
)
add(
DVFilter(
relation = Relations.ID,
condition = DVFilterCondition.IN,
value = listOf(config.spaceView, params.member)
)
)
},
limit = 2,
keys = listOf(
Relations.ID,
Relations.SPACE_ID,
Relations.TARGET_SPACE_ID,
Relations.IDENTITY,
Relations.ICON_IMAGE,
Relations.NAME
)
)
).process(
failure = { e ->
Timber.e(e, "Error while fetching space data and member data").also {
sendToast(e.msg())
}
},
success = { wrappers ->
val spaceView = wrappers.firstOrNull { it.id == config.spaceView }
val member = wrappers.firstOrNull { it.id == params.member }
if (spaceView != null && member != null) {
state.value = State.Success(
member = ObjectWrapper.Participant(member.map),
spaceView = ObjectWrapper.SpaceView(spaceView.map)
)
} else {
state.value = State.Error
}
}
)
} else {
state.value = State.Error
}
}
viewModelScope.launch {
state.collect { curr ->
viewState.value = when (curr) {
is State.Error -> ViewState.Error
is State.Init -> ViewState.Init
is State.Success -> ViewState.Success(
memberName = curr.member.name.orEmpty(),
spaceName = curr.spaceView.name.orEmpty()
)
}
}
}
}
fun onRejectRequestClicked() {
viewModelScope.launch {
when(val curr = state.value) {
is State.Error -> {
// TODO send toast
}
is State.Init -> {
// Do nothing
}
is State.Success -> {
declineSpaceJoinRequest.async(
DeclineSpaceJoinRequest.Params(
space = params.space,
identity = curr.member.identity
)
).fold(
onSuccess = {
isDismissed.value = true
},
onFailure = { e ->
Timber.e(e, "Error while approving join-space request").also {
sendToast(e.msg())
}
}
)
}
}
}
}
fun onJoinAsReaderClicked() {
viewModelScope.launch {
when(val curr = state.value) {
is State.Error -> {
// TODO send toast
}
is State.Init -> {
// Do nothing
}
is State.Success -> {
approveJoinSpaceRequest.async(
ApproveJoinSpaceRequest.Params(
space = params.space,
identity = curr.member.identity,
permissions = ParticipantPermissions.READER
)
).fold(
onSuccess = {
isDismissed.value = true
},
onFailure = { e ->
Timber.e(e, "Error while approving join-space request").also {
sendToast(e.msg())
}
}
)
}
}
}
}
fun onJoinAsEditorClicked() {
viewModelScope.launch {
when(val curr = state.value) {
is State.Error -> {
// TODO send toast
}
is State.Init -> {
// Do nothing
}
is State.Success -> {
approveJoinSpaceRequest.async(
ApproveJoinSpaceRequest.Params(
space = params.space,
identity = curr.member.identity,
permissions = ParticipantPermissions.WRITER
)
).fold(
onSuccess = {
isDismissed.value = true
},
onFailure = { e ->
Timber.e(e, "Error while approving join-space request").also {
sendToast(e.msg())
}
}
)
}
}
}
}
class Factory @Inject constructor(
private val params: Params,
private val approveJoinSpaceRequest: ApproveJoinSpaceRequest,
private val declineSpaceJoinRequest: DeclineSpaceJoinRequest,
private val searchObjects: SearchObjects,
private val spaceManager: SpaceManager
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T = SpaceJoinRequestViewModel(
params = params,
declineSpaceJoinRequest = declineSpaceJoinRequest,
approveJoinSpaceRequest = approveJoinSpaceRequest,
searchObjects = searchObjects,
spaceManager = spaceManager
) as T
}
data class Params(val space: SpaceId, val member: Id)
sealed class State {
object Init : State()
data class Success(
val member: ObjectWrapper.Participant,
val spaceView: ObjectWrapper.SpaceView
) : State()
object Error : State()
}
sealed class ViewState {
object Init: ViewState()
data class Success(val memberName: String, val spaceName: String): ViewState()
object Error: ViewState()
}
}