mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2378 Membership | Enhancement | Membership upgrade screen (#1312)
This commit is contained in:
parent
242694df4d
commit
e34bb538f4
11 changed files with 319 additions and 9 deletions
|
@ -64,6 +64,7 @@ import com.anytypeio.anytype.di.feature.gallery.DaggerGalleryInstallationCompone
|
|||
import com.anytypeio.anytype.di.feature.home.DaggerHomeScreenComponent
|
||||
import com.anytypeio.anytype.di.feature.library.DaggerLibraryComponent
|
||||
import com.anytypeio.anytype.di.feature.membership.DaggerMembershipComponent
|
||||
import com.anytypeio.anytype.di.feature.membership.DaggerMembershipUpdateComponent
|
||||
import com.anytypeio.anytype.di.feature.multiplayer.DaggerRequestJoinSpaceComponent
|
||||
import com.anytypeio.anytype.di.feature.multiplayer.DaggerShareSpaceComponent
|
||||
import com.anytypeio.anytype.di.feature.multiplayer.DaggerSpaceJoinRequestComponent
|
||||
|
@ -1143,6 +1144,10 @@ class ComponentManager(
|
|||
DaggerMembershipComponent.factory().create(findComponentDependencies())
|
||||
}
|
||||
|
||||
val membershipUpgradeComponent = Component {
|
||||
DaggerMembershipUpdateComponent.factory().create(findComponentDependencies())
|
||||
}
|
||||
|
||||
val galleryInstallationsComponent =
|
||||
ComponentWithParams { params: GalleryInstallationViewModel.ViewModelParams ->
|
||||
DaggerGalleryInstallationComponent.builder()
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package com.anytypeio.anytype.di.feature.membership
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
|
||||
import com.anytypeio.anytype.di.common.ComponentDependencies
|
||||
import com.anytypeio.anytype.domain.auth.interactor.GetAccount
|
||||
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.presentation.membership.MembershipUpgradeViewModel
|
||||
import com.anytypeio.anytype.ui.payments.MembershipUpgradeFragment
|
||||
import dagger.Binds
|
||||
import dagger.Component
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
||||
@Component(
|
||||
dependencies = [MembershipUpdateComponentDependencies::class],
|
||||
modules = [
|
||||
MembershipUpdateModule::class,
|
||||
MembershipUpdateModule.Declarations::class
|
||||
]
|
||||
)
|
||||
@PerScreen
|
||||
interface MembershipUpdateComponent {
|
||||
|
||||
@Component.Factory
|
||||
interface Factory {
|
||||
fun create(dependencies: MembershipUpdateComponentDependencies): MembershipUpdateComponent
|
||||
}
|
||||
|
||||
fun inject(fragment: MembershipUpgradeFragment)
|
||||
}
|
||||
|
||||
@Module
|
||||
object MembershipUpdateModule {
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideGetAccountUseCase(
|
||||
repo: AuthRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): GetAccount = GetAccount(repo = repo, dispatcher = dispatchers)
|
||||
|
||||
@Module
|
||||
interface Declarations {
|
||||
|
||||
@PerScreen
|
||||
@Binds
|
||||
fun bindViewModelFactory(
|
||||
factory: MembershipUpgradeViewModel.Factory
|
||||
): ViewModelProvider.Factory
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
interface MembershipUpdateComponentDependencies : ComponentDependencies {
|
||||
fun authRepository(): AuthRepository
|
||||
fun appCoroutineDispatchers(): AppCoroutineDispatchers
|
||||
}
|
|
@ -33,6 +33,7 @@ import com.anytypeio.anytype.di.feature.onboarding.login.OnboardingMnemonicLogin
|
|||
import com.anytypeio.anytype.di.feature.onboarding.signup.OnboardingMnemonicDependencies
|
||||
import com.anytypeio.anytype.di.feature.onboarding.signup.OnboardingSoulCreationDependencies
|
||||
import com.anytypeio.anytype.di.feature.membership.MembershipComponentDependencies
|
||||
import com.anytypeio.anytype.di.feature.membership.MembershipUpdateComponentDependencies
|
||||
import com.anytypeio.anytype.di.feature.relations.RelationCreateFromLibraryDependencies
|
||||
import com.anytypeio.anytype.di.feature.relations.RelationEditDependencies
|
||||
import com.anytypeio.anytype.di.feature.search.GlobalSearchDependencies
|
||||
|
@ -122,7 +123,8 @@ interface MainComponent :
|
|||
MembershipComponentDependencies,
|
||||
GalleryInstallationComponentDependencies,
|
||||
NotificationDependencies,
|
||||
GlobalSearchDependencies
|
||||
GlobalSearchDependencies,
|
||||
MembershipUpdateComponentDependencies
|
||||
{
|
||||
|
||||
fun inject(app: AndroidApplication)
|
||||
|
@ -338,4 +340,9 @@ abstract class ComponentDependenciesModule {
|
|||
@IntoMap
|
||||
@ComponentDependenciesKey(GlobalSearchDependencies::class)
|
||||
abstract fun provideGlobalSearchDependencies(component: MainComponent): ComponentDependencies
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ComponentDependenciesKey(MembershipUpdateComponentDependencies::class)
|
||||
abstract fun provideMembershipUpdateComponentDependencies(component: MainComponent): ComponentDependencies
|
||||
}
|
|
@ -23,6 +23,7 @@ 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
|
||||
import timber.log.Timber
|
||||
|
||||
class SpaceJoinRequestFragment : BaseBottomSheetComposeFragment() {
|
||||
|
||||
|
@ -69,17 +70,19 @@ class SpaceJoinRequestFragment : BaseBottomSheetComposeFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun proceedWithCommand(command: SpaceJoinRequestViewModel.Command?) {
|
||||
when(command) {
|
||||
private fun proceedWithCommand(command: SpaceJoinRequestViewModel.Command) {
|
||||
Timber.d("proceedWithCommand: $command")
|
||||
when (command) {
|
||||
SpaceJoinRequestViewModel.Command.NavigateToMembership -> {
|
||||
findNavController().navigate(R.id.paymentsScreen)
|
||||
}
|
||||
null -> {
|
||||
// Do nothing.
|
||||
SpaceJoinRequestViewModel.Command.NavigateToMembershipUpdate -> {
|
||||
findNavController().navigate(R.id.membershipUpdateScreen)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().spaceJoinRequestComponent.get(
|
||||
SpaceJoinRequestViewModel.VmParams(
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package com.anytypeio.anytype.ui.payments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_ui.common.ComposeDialogView
|
||||
import com.anytypeio.anytype.core_ui.extensions.color
|
||||
import com.anytypeio.anytype.core_utils.intents.SystemAction
|
||||
import com.anytypeio.anytype.core_utils.intents.proceedWithAction
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.payments.screens.MembershipUpgradeScreen
|
||||
import com.anytypeio.anytype.presentation.membership.MembershipUpgradeViewModel
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import javax.inject.Inject
|
||||
|
||||
class MembershipUpgradeFragment : BaseBottomSheetComposeFragment() {
|
||||
|
||||
@Inject
|
||||
lateinit var factory: MembershipUpgradeViewModel.Factory
|
||||
private val vm by viewModels<MembershipUpgradeViewModel> { factory }
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
return ComposeDialogView(context = requireContext(), dialog = requireDialog()).apply {
|
||||
dialog?.setOnShowListener { dg ->
|
||||
val bottomSheet = (dg as? BottomSheetDialog)?.findViewById<FrameLayout>(
|
||||
com.google.android.material.R.id.design_bottom_sheet
|
||||
)
|
||||
bottomSheet?.setBackgroundColor(requireContext().color(android.R.color.transparent))
|
||||
}
|
||||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
MembershipUpgradeScreen(
|
||||
onDismiss = { },
|
||||
onButtonClicked = vm::onContactButtonClicked
|
||||
)
|
||||
LaunchedEffect(Unit) {
|
||||
vm.commands.collect { command ->
|
||||
when (command) {
|
||||
is MembershipUpgradeViewModel.Command.ShowEmail -> {
|
||||
proceedWithEmailCreate(command.account)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithEmailCreate(accountId: Id) {
|
||||
val mail = resources.getString(R.string.payments_email_to)
|
||||
val subject = resources.getString(R.string.payments_email_subject, accountId)
|
||||
val body = resources.getString(R.string.payments_email_body)
|
||||
val mailBody = mail +
|
||||
"?subject=$subject" +
|
||||
"&body=$body"
|
||||
proceedWithAction(SystemAction.MailTo(mailBody))
|
||||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().membershipUpgradeComponent.get().inject(this)
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
componentManager().membershipUpgradeComponent.release()
|
||||
}
|
||||
}
|
|
@ -276,6 +276,10 @@
|
|||
android:id="@+id/paymentsScreen"
|
||||
android:name="com.anytypeio.anytype.ui.payments.MembershipFragment" />
|
||||
|
||||
<dialog
|
||||
android:id="@+id/membershipUpdateScreen"
|
||||
android:name="com.anytypeio.anytype.ui.payments.MembershipUpgradeFragment" />
|
||||
|
||||
<dialog
|
||||
android:id="@+id/galleryInstallationScreen"
|
||||
android:name="com.anytypeio.anytype.ui.gallery.GalleryInstallationFragment" />
|
||||
|
|
|
@ -1640,11 +1640,15 @@ Please provide specific details of your needs here.</string>
|
|||
<string name="membership_support_already_acquired">You’ve already acquired a Membership plan using another Anytype account.</string>
|
||||
<string name="membership_support_different_subscription">Found a subscription with a different id</string>
|
||||
<string name="membership_support_more_then_one_subscription">Found more than one subscription</string>
|
||||
<string name="multiplayer_space_join_request_participants_error">Space participant's error</string>
|
||||
<string name="multiplayer_space_join_request_new_member_error">Request's member error</string>
|
||||
<string name="multiplayer_space_join_request_participants_error">Space participant\'s error</string>
|
||||
<string name="multiplayer_space_join_request_new_member_error">Request\'s member error</string>
|
||||
<string name="multiplayer_space_join_request_current_user_error">Current user status error</string>
|
||||
<string name="multiplayer_space_join_request_membership_status_error">Current membership status error</string>
|
||||
|
||||
<string name="membership_upgrade_title">Membership upgrade</string>
|
||||
<string name="membership_upgrade_description">Reach us for extra storage, space editors, or more shared spaces. Anytype team will provide details and conditions tailored to your needs.</string>
|
||||
<string name="membership_upgrade_button">Contact Anytype Team</string>
|
||||
|
||||
<plurals name="period_years">
|
||||
<item quantity="one">year</item>
|
||||
<item quantity="other">%d years</item>
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
package com.anytypeio.anytype.payments.screens
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_ui.foundation.Dragger
|
||||
import com.anytypeio.anytype.core_ui.views.BodyRegular
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonPrimary
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonSize
|
||||
import com.anytypeio.anytype.core_ui.views.HeadlineHeading
|
||||
import com.anytypeio.anytype.payments.R
|
||||
|
||||
@Composable
|
||||
fun MembershipUpgradeScreen(
|
||||
onButtonClicked: () -> Unit,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
Log.d("MembershipUpgradeScreen", "onButtonClicked: $onButtonClicked, onDismiss: $onDismiss")
|
||||
ElevatedCard(
|
||||
modifier = Modifier.padding(20.dp),
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = colorResource(id = R.color.background_primary)
|
||||
),
|
||||
elevation = CardDefaults.elevatedCardElevation(
|
||||
defaultElevation = 16.dp
|
||||
),
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 6.dp)
|
||||
.fillMaxWidth(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Dragger()
|
||||
}
|
||||
Spacer(modifier = Modifier.height(19.dp))
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp),
|
||||
text = stringResource(id = R.string.membership_upgrade_title),
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
style = HeadlineHeading,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
Spacer(modifier = Modifier.height(14.dp))
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp),
|
||||
text = stringResource(id = R.string.membership_upgrade_description),
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
style = BodyRegular,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
Spacer(modifier = Modifier.height(30.dp))
|
||||
ButtonPrimary(
|
||||
text = stringResource(id = R.string.membership_upgrade_button),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp),
|
||||
onClick = { onButtonClicked() },
|
||||
size = ButtonSize.LargeSecondary
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Preview(
|
||||
name = "Dark Mode",
|
||||
showBackground = true,
|
||||
uiMode = Configuration.UI_MODE_NIGHT_YES
|
||||
)
|
||||
@Preview(
|
||||
name = "Light Mode",
|
||||
showBackground = true,
|
||||
uiMode = Configuration.UI_MODE_NIGHT_NO
|
||||
)
|
||||
@Composable
|
||||
fun MembershipUpgradeScreenPreview() {
|
||||
MembershipUpgradeScreen(onDismiss = {}, onButtonClicked = {})
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.anytypeio.anytype.presentation.membership
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.domain.auth.interactor.GetAccount
|
||||
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MembershipUpgradeViewModel(
|
||||
private val getAccount: GetAccount
|
||||
) : ViewModel() {
|
||||
|
||||
val commands = MutableSharedFlow<Command>(0)
|
||||
|
||||
fun onContactButtonClicked() {
|
||||
viewModelScope.launch {
|
||||
val account = getAccount.async(Unit).getOrNull() ?: return@launch
|
||||
commands.emit(Command.ShowEmail(account.id))
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Command {
|
||||
data class ShowEmail(val account: Id) : Command()
|
||||
}
|
||||
|
||||
class Factory @Inject constructor(
|
||||
private val getAccount: GetAccount,
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return MembershipUpgradeViewModel(
|
||||
getAccount = getAccount
|
||||
) as T
|
||||
}
|
||||
}
|
||||
}
|
|
@ -392,7 +392,7 @@ class SpaceJoinRequestViewModel(
|
|||
if (isPossibleToUpgrade) {
|
||||
_commands.emit(Command.NavigateToMembership)
|
||||
} else {
|
||||
//todo navigate to membership email screen
|
||||
_commands.emit(Command.NavigateToMembershipUpdate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -476,6 +476,7 @@ class SpaceJoinRequestViewModel(
|
|||
|
||||
sealed class Command {
|
||||
data object NavigateToMembership : Command()
|
||||
data object NavigateToMembershipUpdate : Command()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ class EditorCreateBlockTest : EditorPresentationTestSetup() {
|
|||
position = Position.BOTTOM,
|
||||
prototype = Block.Prototype.Link(
|
||||
target = linkToObject,
|
||||
cardStyle = Block.Content.Link.CardStyle.TEXT,
|
||||
cardStyle = Block.Content.Link.CardStyle.CARD,
|
||||
iconSize = Block.Content.Link.IconSize.SMALL,
|
||||
description = Block.Content.Link.Description.NONE
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue