Skip to content

Commit

Permalink
feat: alerts for non paying users [WPB-1826] (#3715)
Browse files Browse the repository at this point in the history
  • Loading branch information
m-zagorski authored Dec 16, 2024
1 parent a59ff2e commit 05c53e8
Show file tree
Hide file tree
Showing 8 changed files with 341 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,9 @@ class CallsModule {
@Provides
fun provideIsEligibleToStartCall(callsScope: CallsScope) =
callsScope.isEligibleToStartCall

@ViewModelScoped
@Provides
fun provideObserveConferenceCallingEnabledUseCase(callsScope: CallsScope) =
callsScope.observeConferenceCallingEnabled
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Wire
* Copyright (C) 2024 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.android.ui.common.dialogs.calling

import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.wire.android.R
import com.wire.android.ui.common.DialogTextSuffixLink
import com.wire.android.ui.common.WireDialog
import com.wire.android.ui.common.WireDialogButtonProperties
import com.wire.android.ui.common.WireDialogButtonType

@Composable
fun CallingFeatureActivatedDialog(onDialogDismiss: () -> Unit) {
WireDialog(
title = stringResource(id = R.string.calling_feature_enabled_title_alert),
text = stringResource(id = R.string.calling_feature_enabled_message_alert),
onDismiss = onDialogDismiss,
textSuffixLink = DialogTextSuffixLink(
linkText = stringResource(R.string.calling_feature_enabled_message_link_alert),
linkUrl = stringResource(R.string.url_wire_enterprise)
),
optionButton1Properties = WireDialogButtonProperties(
onClick = onDialogDismiss,
text = stringResource(id = R.string.label_ok),
type = WireDialogButtonType.Primary
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package com.wire.android.ui.common.dialogs.calling
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.wire.android.R
import com.wire.android.ui.common.DialogTextSuffixLink
import com.wire.android.ui.common.WireDialog
import com.wire.android.ui.common.WireDialogButtonProperties
import com.wire.android.ui.common.WireDialogButtonType
Expand All @@ -38,3 +39,47 @@ fun CallingFeatureUnavailableDialog(onDialogDismiss: () -> Unit) {
)
)
}

@Composable
fun CallingFeatureUnavailableTeamMemberDialog(onDialogDismiss: () -> Unit) {
WireDialog(
title = stringResource(id = R.string.calling_feature_unavailable_title_alert),
text = stringResource(id = R.string.calling_feature_unavailable_team_member_message_alert),
onDismiss = onDialogDismiss,
optionButton1Properties = WireDialogButtonProperties(
onClick = onDialogDismiss,
text = stringResource(id = R.string.label_ok),
type = WireDialogButtonType.Primary
)
)
}

@Composable
fun CallingFeatureUnavailableTeamAdminDialog(
onUpgradeAction: (String) -> Unit,
onDialogDismiss: () -> Unit
) {
val upgradeLink = stringResource(R.string.url_team_management_login)
WireDialog(
title = stringResource(id = R.string.calling_feature_unavailable_team_admin_title_alert),
text = stringResource(id = R.string.calling_feature_unavailable_team_admin_message_alert),
onDismiss = onDialogDismiss,
textSuffixLink = DialogTextSuffixLink(
linkText = stringResource(R.string.calling_feature_unavailable_team_admin_message_link_alert),
linkUrl = stringResource(R.string.url_team_management_login)
),
optionButton2Properties = WireDialogButtonProperties(
onClick = {
onUpgradeAction(upgradeLink)
onDialogDismiss()
},
text = stringResource(id = R.string.calling_feature_unavailable_team_admin_upgrade_action_alert),
type = WireDialogButtonType.Primary
),
optionButton1Properties = WireDialogButtonProperties(
onClick = onDialogDismiss,
text = stringResource(id = R.string.label_cancel),
type = WireDialogButtonType.Secondary
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ import com.wire.android.ui.common.dialogs.InvalidLinkDialog
import com.wire.android.ui.common.dialogs.PermissionPermanentlyDeniedDialog
import com.wire.android.ui.common.dialogs.SureAboutMessagingInDegradedConversationDialog
import com.wire.android.ui.common.dialogs.VisitLinkDialog
import com.wire.android.ui.common.dialogs.calling.CallingFeatureActivatedDialog
import com.wire.android.ui.common.dialogs.calling.CallingFeatureUnavailableDialog
import com.wire.android.ui.common.dialogs.calling.CallingFeatureUnavailableTeamAdminDialog
import com.wire.android.ui.common.dialogs.calling.CallingFeatureUnavailableTeamMemberDialog
import com.wire.android.ui.common.dialogs.calling.ConfirmStartCallDialog
import com.wire.android.ui.common.dialogs.calling.JoinAnywayDialog
import com.wire.android.ui.common.dialogs.calling.OngoingActiveCallDialog
Expand Down Expand Up @@ -173,6 +176,7 @@ import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.message.MessageAssetStatus
import com.wire.kalium.logic.data.message.SelfDeletionTimer
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.data.user.type.UserType
import com.wire.kalium.logic.feature.call.usecase.ConferenceCallingResult
import kotlinx.collections.immutable.PersistentMap
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -299,6 +303,12 @@ fun ConversationScreen(
}
}

LaunchedEffect(Unit) {
conversationListCallViewModel.callingEnabled.collect {
showDialog.value = ConversationScreenDialogType.CALLING_FEATURE_ACTIVATED
}
}

conversationMigrationViewModel.migratedConversationId?.let { migratedConversationId ->
navigator.navigate(
NavigationCommand(
Expand Down Expand Up @@ -387,9 +397,30 @@ fun ConversationScreen(
}

ConversationScreenDialogType.CALLING_FEATURE_UNAVAILABLE -> {
CallingFeatureUnavailableDialog(onDialogDismiss = {
CallingFeatureUnavailableDialog {
showDialog.value = ConversationScreenDialogType.NONE
})
}
}

ConversationScreenDialogType.CALLING_FEATURE_UNAVAILABLE_TEAM_MEMBER -> {
CallingFeatureUnavailableTeamMemberDialog {
showDialog.value = ConversationScreenDialogType.NONE
}
}

ConversationScreenDialogType.CALLING_FEATURE_UNAVAILABLE_TEAM_ADMIN -> {
CallingFeatureUnavailableTeamAdminDialog(
onUpgradeAction = uriHandler::openUri,
onDialogDismiss = {
showDialog.value = ConversationScreenDialogType.NONE
}
)
}

ConversationScreenDialogType.CALLING_FEATURE_ACTIVATED -> {
CallingFeatureActivatedDialog {
showDialog.value = ConversationScreenDialogType.NONE
}
}

ConversationScreenDialogType.VERIFICATION_DEGRADED -> {
Expand Down Expand Up @@ -771,7 +802,16 @@ private fun startCallIfPossible(
}

ConferenceCallingResult.Disabled.OngoingCall -> ConversationScreenDialogType.ONGOING_ACTIVE_CALL
ConferenceCallingResult.Disabled.Unavailable -> ConversationScreenDialogType.CALLING_FEATURE_UNAVAILABLE
ConferenceCallingResult.Disabled.Unavailable -> {
when (conversationListCallViewModel.selfTeamRole.value) {
UserType.INTERNAL -> ConversationScreenDialogType.CALLING_FEATURE_UNAVAILABLE_TEAM_MEMBER
UserType.OWNER,
UserType.ADMIN -> ConversationScreenDialogType.CALLING_FEATURE_UNAVAILABLE_TEAM_ADMIN

else -> ConversationScreenDialogType.CALLING_FEATURE_UNAVAILABLE
}
}

else -> ConversationScreenDialogType.NONE
}
showDialog.value = dialogValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,8 @@ enum class ConversationScreenDialogType {
CALL_CONFIRMATION,
PING_CONFIRMATION,
CALLING_FEATURE_UNAVAILABLE,
CALLING_FEATURE_UNAVAILABLE_TEAM_MEMBER,
CALLING_FEATURE_UNAVAILABLE_TEAM_ADMIN,
CALLING_FEATURE_ACTIVATED,
NONE
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,22 @@ import com.wire.kalium.logic.data.conversation.ConversationDetails
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.id.QualifiedID
import com.wire.kalium.logic.data.sync.SyncState
import com.wire.kalium.logic.data.user.type.UserType
import com.wire.kalium.logic.feature.call.usecase.AnswerCallUseCase
import com.wire.kalium.logic.feature.call.usecase.ConferenceCallingResult
import com.wire.kalium.logic.feature.call.usecase.EndCallUseCase
import com.wire.kalium.logic.feature.call.usecase.IsEligibleToStartCallUseCase
import com.wire.kalium.logic.feature.call.usecase.ObserveConferenceCallingEnabledUseCase
import com.wire.kalium.logic.feature.call.usecase.ObserveEstablishedCallsUseCase
import com.wire.kalium.logic.feature.call.usecase.ObserveOngoingCallsUseCase
import com.wire.kalium.logic.feature.conversation.ObserveConversationDetailsUseCase
import com.wire.kalium.logic.feature.conversation.ObserveDegradedConversationNotifiedUseCase
import com.wire.kalium.logic.feature.conversation.SetUserInformedAboutVerificationUseCase
import com.wire.kalium.logic.feature.user.GetSelfUserUseCase
import com.wire.kalium.logic.sync.ObserveSyncStateUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
Expand All @@ -64,14 +68,18 @@ class ConversationListCallViewModel @Inject constructor(
private val isConferenceCallingEnabled: IsEligibleToStartCallUseCase,
private val observeConversationDetails: ObserveConversationDetailsUseCase,
private val setUserInformedAboutVerification: SetUserInformedAboutVerificationUseCase,
private val observeDegradedConversationNotified: ObserveDegradedConversationNotifiedUseCase
private val observeDegradedConversationNotified: ObserveDegradedConversationNotifiedUseCase,
private val observeConferenceCallingEnabled: ObserveConferenceCallingEnabledUseCase,
private val getSelf: GetSelfUserUseCase
) : SavedStateViewModel(savedStateHandle) {

private val conversationNavArgs: ConversationNavArgs = savedStateHandle.navArgs()
val conversationId: QualifiedID = conversationNavArgs.conversationId

var conversationCallViewState by mutableStateOf(ConversationCallViewState())
val shouldInformAboutVerification = mutableStateOf(false)
val selfTeamRole = mutableStateOf(UserType.GUEST)
val callingEnabled = MutableSharedFlow<Unit>(replay = 1)

var establishedCallConversationId: QualifiedID? = null

Expand All @@ -80,6 +88,15 @@ class ConversationListCallViewModel @Inject constructor(
observeEstablishedCall()
observeParticipantsForConversation()
observeInformedAboutDegradedVerification()
observeSelfTeamRole()
observeCallingActivatedEvent()
}

private fun observeCallingActivatedEvent() {
viewModelScope.launch {
observeConferenceCallingEnabled()
.collectLatest { callingEnabled.emit(Unit) }
}
}

private fun observeParticipantsForConversation() {
Expand All @@ -91,6 +108,14 @@ class ConversationListCallViewModel @Inject constructor(
}
}

private fun observeSelfTeamRole() {
viewModelScope.launch {
getSelf().collectLatest { self ->
selfTeamRole.value = self.userType
}
}
}

private fun observeInformedAboutDegradedVerification() = viewModelScope.launch {
observeDegradedConversationNotified(conversationId).collect { shouldInformAboutVerification.value = !it }
}
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@
<string name="url_how_to_add_folders" translatable="false">https://support.wire.com/hc/articles/360002855817</string>
<string name="url_wire_plans" translatable="false">https://wire.com/pricing</string>
<string name="url_team_management" translatable="false">https://teams.wire.com/</string>
<string name="url_team_management_login" translatable="false">https://teams.wire.com/login</string>
<string name="url_wire_enterprise" translatable="false">https://wire.com/en/enterprise</string>
<!-- Navigation -->
<string name="vault_screen_title">Vault</string>
<string name="archive_screen_title">Archive</string>
Expand Down Expand Up @@ -981,6 +983,14 @@
<string name="calling_ongoing_double_tap_to_go_back">Double tap to go back</string>
<string name="calling_feature_unavailable_title_alert">Feature unavailable</string>
<string name="calling_feature_unavailable_message_alert">The option to initiate a conference call is only available in the paid version of Wire.</string>
<string name="calling_feature_unavailable_team_member_message_alert">To start a conference call, your team needs to upgrade to the Enterprise plan.</string>
<string name="calling_feature_unavailable_team_admin_title_alert">Upgrade to Enterprise</string>
<string name="calling_feature_unavailable_team_admin_message_alert">Your team is currently on the free Basic plan. Upgrade to Enterprise for access to features such as starting conferences and more.</string>
<string name="calling_feature_unavailable_team_admin_message_link_alert">Learn more about Wire\'s pricing</string>
<string name="calling_feature_unavailable_team_admin_upgrade_action_alert">Upgrade now</string>
<string name="calling_feature_enabled_title_alert">Wire Enterprise</string>
<string name="calling_feature_enabled_message_alert">Your team was upgraded to Wire Enterprise, which gives you access to features such as conference calls and more.</string>
<string name="calling_feature_enabled_message_link_alert">Learn more about Wire Enterprise</string>
<string name="calling_screen_connecting_until_call_established">Connecting…</string>
<string name="calling_confirm_start_call_title_dialog">Start a call</string>
<string name="calling_confirm_start_call_description_dialog">Are you sure you want to call %1$s people?</string>
Expand Down
Loading

0 comments on commit 05c53e8

Please sign in to comment.