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

DROID-3703 Invite | Join without approve link, success notification (#2470)

This commit is contained in:
Konstantin Ivanov 2025-05-27 14:46:51 +02:00 committed by konstantiniiv
parent 42e227ee69
commit 9796249baa
7 changed files with 115 additions and 59 deletions

View file

@ -7,6 +7,9 @@ import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.analytics.base.EventsDictionary.screenInviteRequest
import com.anytypeio.anytype.analytics.base.EventsDictionary.screenRequestSent
import com.anytypeio.anytype.analytics.base.sendEvent
import com.anytypeio.anytype.core_models.Notification
import com.anytypeio.anytype.core_models.NotificationPayload
import com.anytypeio.anytype.core_models.NotificationStatus
import com.anytypeio.anytype.core_models.multiplayer.MultiplayerError
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteError
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteView
@ -27,6 +30,7 @@ import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.common.TypedViewState
import javax.inject.Inject
import kotlin.random.Random
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@ -130,54 +134,86 @@ class RequestJoinSpaceViewModel(
}
fun onRequestToJoinClicked() {
when(val curr = state.value) {
is TypedViewState.Success -> {
joinSpaceRequestJob?.cancel()
joinSpaceRequestJob = viewModelScope.launch {
val fileKey = spaceInviteResolver.parseFileKey(params.link)
val contentId = spaceInviteResolver.parseContentId(params.link)
if (contentId != null && fileKey != null) {
isRequestInProgress.value = true
sendJoinSpaceRequest.async(
SendJoinSpaceRequest.Params(
space = curr.data.space,
network = configStorage.getOrNull()?.network,
inviteFileKey = fileKey,
inviteContentId = contentId
)
).fold(
onFailure = { e ->
Timber.e(e, "Error while sending space join request")
if (e is MultiplayerError.Generic) {
commands.emit(Command.ShowGenericMultiplayerError(e))
} else {
sendToast(e.msg())
}
},
onSuccess = {
analytics.sendEvent(eventName = screenRequestSent)
if (notificator.areNotificationsEnabled) {
if (!curr.data.withoutApprove) {
commands.emit(Command.Toast.RequestSent)
}
commands.emit(Command.Dismiss)
} else {
if (!curr.data.withoutApprove) {
commands.emit(Command.Toast.RequestSent)
}
showEnableNotificationDialog.value = true
}
}
)
isRequestInProgress.value = false
}
}
} else -> {
// Do nothing.
val currentState = state.value
if (currentState !is TypedViewState.Success) return
joinSpaceRequestJob?.cancel()
joinSpaceRequestJob = viewModelScope.launch {
val fileKey = spaceInviteResolver.parseFileKey(params.link)
val contentId = spaceInviteResolver.parseContentId(params.link)
if (fileKey == null || contentId == null) {
Timber.w("Could not parse invite link in onRequestToJoinClicked: ${params.link}")
return@launch
}
isRequestInProgress.value = true
val params = SendJoinSpaceRequest.Params(
space = currentState.data.space,
network = configStorage.getOrNull()?.network,
inviteFileKey = fileKey,
inviteContentId = contentId
)
sendJoinSpaceRequest.async(params).fold(
onFailure = { handleJoinRequestFailure(it) },
onSuccess = { handleJoinRequestSuccess(currentState.data) }
)
isRequestInProgress.value = false
}
}
private suspend fun handleJoinRequestFailure(error: Throwable) {
Timber.e(error, "Error while sending space join request")
when (error) {
is MultiplayerError.Generic -> commands.emit(Command.ShowGenericMultiplayerError(error))
else -> sendToast(error.msg())
}
}
private suspend fun handleJoinRequestSuccess(data: SpaceInviteView) {
analytics.sendEvent(eventName = screenRequestSent)
val shouldNotify = data.withoutApprove
val notificationsEnabled = notificator.areNotificationsEnabled
if (shouldNotify) {
sendApprovalNotification(data)
}
if (notificationsEnabled) {
if (!shouldNotify) {
commands.emit(Command.Toast.RequestSent)
}
commands.emit(Command.Dismiss)
} else {
if (!shouldNotify) {
commands.emit(Command.Toast.RequestSent)
}
showEnableNotificationDialog.value = true
}
}
private fun createApprovalNotification(data: SpaceInviteView): Notification {
return Notification(
id = Random.nextInt().toString(),
createTime = System.currentTimeMillis(),
status = NotificationStatus.CREATED,
isLocal = true,
payload = NotificationPayload.ParticipantRequestApproved(
spaceId = data.space,
spaceName = data.spaceName
),
space = data.space
)
}
private fun sendApprovalNotification(data: SpaceInviteView) {
notificator.notify(createApprovalNotification(data))
}
fun onCancelJoinSpaceRequestClicked() {
joinSpaceRequestJob?.cancel()
isRequestInProgress.value = false

View file

@ -80,7 +80,8 @@ class NotificationsViewModel(
notification = notification.id,
space = payload.spaceId,
spaceName = payload.spaceName,
isReadOnly = !payload.permissions.isOwnerOrEditor()
isReadOnly = payload.permissions == null
|| payload.permissions?.isOwnerOrEditor() != true
)
}
is NotificationPayload.ParticipantRemove -> {

View file

@ -6,6 +6,7 @@ import com.anytypeio.anytype.core_models.NetworkMode
import com.anytypeio.anytype.core_models.NetworkModeConfig
import com.anytypeio.anytype.domain.auth.interactor.GetMnemonic
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.deeplink.PendingIntentStore
import com.anytypeio.anytype.domain.device.NetworkConnectionStatus
import com.anytypeio.anytype.domain.network.NetworkModeProvider
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
@ -40,8 +41,11 @@ class OnboardingMnemonicViewModelTest {
@Mock
private lateinit var networkModeProvider: NetworkModeProvider
lateinit var pendingIntentStore: PendingIntentStore
@Before
fun setup() {
pendingIntentStore = PendingIntentStore()
MockitoAnnotations.openMocks(this)
}
@ -139,7 +143,8 @@ class OnboardingMnemonicViewModelTest {
analytics = analytics,
configStorage = configStorage,
networkModeProvider = networkModeProvider,
networkConnectionStatus = networkConnectionStatus
networkConnectionStatus = networkConnectionStatus,
pendingIntentStore = pendingIntentStore
)
}
}