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

DROID-3629 Onboarding | Email screen (#2395)

This commit is contained in:
Konstantin Ivanov 2025-05-13 10:29:37 +02:00 committed by konstantiniiv
parent 734eeecbc1
commit 94042fe4b9
16 changed files with 474 additions and 34 deletions

View file

@ -3,6 +3,7 @@ package com.anytypeio.anytype.di.feature.onboarding.signup
import androidx.lifecycle.ViewModelProvider
import com.anytypeio.anytype.CrashReporter
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.auth.interactor.CreateAccount
@ -16,7 +17,9 @@ import com.anytypeio.anytype.domain.device.PathProvider
import com.anytypeio.anytype.domain.misc.LocaleProvider
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.domain.`object`.ImportGetStartedUseCase
import com.anytypeio.anytype.domain.payments.SetMembershipEmail
import com.anytypeio.anytype.domain.platform.InitialParamsProvider
import com.anytypeio.anytype.domain.resources.StringResourceProvider
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
import com.anytypeio.anytype.domain.spaces.SpaceDeletedStatusWatcher
import com.anytypeio.anytype.domain.subscriptions.GlobalSubscriptionManager
@ -94,6 +97,14 @@ object OnboardingSoulCreationModule {
dispatchers = dispatchers
)
@JvmStatic
@Provides
@SoulCreationScreenScope
fun provideSetMembershipEmail(
repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
): SetMembershipEmail = SetMembershipEmail(repo = repo, dispatchers = dispatchers)
@Module
interface Declarations {
@Binds
@ -119,6 +130,7 @@ interface OnboardingSoulCreationDependencies : ComponentDependencies {
fun userPermissionProvider(): UserPermissionProvider
fun awaitAccountStartManager(): AwaitAccountStartManager
fun globalSubscriptionManager(): GlobalSubscriptionManager
fun stringResourceProvider(): StringResourceProvider
}
@Scope

View file

@ -66,7 +66,6 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.fragment.findNavController
import androidx.navigation.navArgument
import androidx.navigation.navOptions
import com.anytypeio.anytype.BuildConfig.USE_EDGE_TO_EDGE
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.Id
@ -74,7 +73,6 @@ import com.anytypeio.anytype.core_models.NO_VALUE
import com.anytypeio.anytype.core_ui.BuildConfig.LIBRARY_PACKAGE_NAME
import com.anytypeio.anytype.core_ui.MNEMONIC_WORD_COUNT
import com.anytypeio.anytype.core_ui.MnemonicPhrasePaletteColors
import com.anytypeio.anytype.core_ui.foundation.GenericAlert
import com.anytypeio.anytype.core_ui.views.BaseAlertDialog
import com.anytypeio.anytype.core_utils.ext.argOrNull
import com.anytypeio.anytype.core_utils.ext.shareFirstFileFromPath
@ -94,6 +92,7 @@ import com.anytypeio.anytype.ui.home.HomeScreenFragment
import com.anytypeio.anytype.ui.onboarding.screens.AuthScreenWrapper
import com.anytypeio.anytype.ui.onboarding.screens.signin.RecoveryScreenWrapper
import com.anytypeio.anytype.ui.onboarding.screens.signup.MnemonicPhraseScreenWrapper
import com.anytypeio.anytype.ui.onboarding.screens.signup.SetEmailWrapper
import com.anytypeio.anytype.ui.onboarding.screens.signup.SetProfileNameWrapper
import com.anytypeio.anytype.ui.vault.VaultFragment
import com.google.android.exoplayer2.ExoPlayer
@ -377,6 +376,40 @@ class OnboardingFragment : Fragment() {
)
BackHandler { onBackClicked() }
}
composable(
route = "${OnboardingNavigation.setEmail}?$ONBOARDING_NAME_PARAM={$ONBOARDING_NAME_PARAM}",
arguments = listOf(
navArgument(ONBOARDING_NAME_PARAM) {
type = NavType.StringType
defaultValue = ""
nullable = false
}
),
enterTransition = {
fadeIn(tween(ANIMATION_LENGTH_FADE))
},
exitTransition = {
fadeOut(tween(ANIMATION_LENGTH_FADE))
}
) {
val focus = LocalFocusManager.current
val onBackClicked : () -> Unit = {
val lastDestination = navController.currentBackStackEntry
if (lastDestination?.destination?.route?.startsWith(OnboardingNavigation.setEmail) == true) {
focus.clearFocus(true)
navController.popBackStack()
} else {
Timber.d("Skipping exit click...")
}
}
currentPage.value = OnboardingPage.SET_EMAIL
backButtonCallback.value = onBackClicked
AddEmail(
navController = navController,
onBackClicked = onBackClicked
)
BackHandler { onBackClicked() }
}
}
}
@ -555,6 +588,16 @@ class OnboardingFragment : Fragment() {
is OnboardingSetProfileNameViewModel.Navigation.GoBack -> {
//
}
is OnboardingSetProfileNameViewModel.Navigation.NavigateToAddEmailScreen -> {
if (keyboardInsets.getBottom(density) > 0) {
focusManager.clearFocus(force = true)
delay(KEYBOARD_HIDE_DELAY)
}
navController.navigate(
route = "${OnboardingNavigation.setEmail}?$ONBOARDING_NAME_PARAM=${command.name}",
)
}
}
}
}
@ -731,6 +774,63 @@ class OnboardingFragment : Fragment() {
}
}
@Composable
private fun AddEmail(
navController: NavHostController,
onBackClicked: () -> Unit
) {
val component = componentManager().onboardingSoulCreationComponent
val vm = daggerViewModel { component.get().getViewModel() }
val focusManager = LocalFocusManager.current
val keyboardInsets = WindowInsets.ime
val density = LocalDensity.current
val name = navController.currentBackStackEntry?.arguments?.getString(ONBOARDING_NAME_PARAM) ?: ""
SetEmailWrapper(
viewModel = vm,
name = name,
onBackClicked = onBackClicked
)
LaunchedEffect(Unit) {
vm.navigation.collect { command ->
when (command) {
is OnboardingSetProfileNameViewModel.Navigation.NavigateToMnemonic -> {
if (keyboardInsets.getBottom(density) > 0) {
focusManager.clearFocus(force = true)
delay(KEYBOARD_HIDE_DELAY)
}
val space = command.space
val startingObject = command.startingObject
navController.navigate(
route = buildString {
append("${OnboardingNavigation.mnemonic}?$ONBOARDING_SPACE_PARAM=${space.id}")
startingObject?.let { append("&$ONBOARDING_STARTING_OBJECT_PARAM=${it}") }
}
)
}
is OnboardingSetProfileNameViewModel.Navigation.GoBack -> {
//
}
is OnboardingSetProfileNameViewModel.Navigation.NavigateToAddEmailScreen -> {
//do nothing
}
}
}
}
LaunchedEffect(Unit) {
vm.toasts.collect {
toast(it)
}
}
DisposableEffect(Unit) {
onDispose { component.release() }
}
}
private fun getVideoPlayer(context: Context, videoPath: Uri): Player {
val player = ExoPlayer.Builder(context).build()
val source = DefaultDataSource.Factory(
@ -772,6 +872,8 @@ class OnboardingFragment : Fragment() {
private const val ONBOARDING_SPACE_PARAM = "space"
private const val ONBOARDING_STARTING_OBJECT_PARAM = "startingObject"
private const val ONBOARDING_NAME_PARAM = "name"
}
}

View file

@ -6,5 +6,5 @@ object OnboardingNavigation {
const val void = "void"
const val mnemonic = "mnemonic"
const val setProfileName = "createSoul"
const val enterTheVoid = "enterTheVoid"
const val setEmail = "setEmail"
}

View file

@ -7,5 +7,6 @@ enum class OnboardingPage(val num: Int, val visible: Boolean) {
SET_PROFILE_NAME(1, false),
SOUL_CREATION_ANIM(4, false),
RECOVERY(5, false),
ENTER_THE_VOID(6, false)
ENTER_THE_VOID(6, false),
SET_EMAIL(3, false)
}

View file

@ -0,0 +1,240 @@
package com.anytypeio.anytype.ui.onboarding.screens.signup
import android.util.Patterns
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
import com.anytypeio.anytype.core_ui.views.ButtonSize
import com.anytypeio.anytype.core_ui.views.Caption1Regular
import com.anytypeio.anytype.core_ui.views.HeadlineTitleSemibold
import com.anytypeio.anytype.core_ui.views.OnBoardingButtonPrimary
import com.anytypeio.anytype.core_ui.views.OnBoardingButtonSecondary
import com.anytypeio.anytype.core_ui.views.PreviewTitle1Regular
import com.anytypeio.anytype.core_ui.views.UXBody
import com.anytypeio.anytype.presentation.onboarding.signup.OnboardingSetProfileNameViewModel
import kotlin.also
import kotlin.text.isNotEmpty
@Composable
fun SetEmailWrapper(
viewModel: OnboardingSetProfileNameViewModel,
name: String,
onBackClicked: () -> Unit,
) {
OnboardingEmailScreen(
onContinueClicked = { email ->
viewModel.onEmailContinueClicked(
name = name,
email = email
)
},
onSkipClicked = {
viewModel.onEmailSkippedClicked(
name = name,
)
},
isLoading = viewModel.state
.collectAsStateWithLifecycle()
.value is OnboardingSetProfileNameViewModel.ScreenState.Loading,
onBackClicked = onBackClicked
)
}
@Composable
fun OnboardingEmailScreen(
onContinueClicked: (String) -> Unit,
onSkipClicked: () -> Unit,
onBackClicked: () -> Unit,
isLoading: Boolean
) {
var innerValue by remember { mutableStateOf(TextFieldValue()) }
var isError by remember { mutableStateOf(false) }
val focusRequester = remember { FocusRequester() }
val keyboardController = LocalSoftwareKeyboardController.current
fun isValidEmail(email: String): Boolean {
return Patterns.EMAIL_ADDRESS.matcher(email).matches()
}
fun validateAndSubmit() {
if (isValidEmail(innerValue.text)) {
isError = false
focusRequester.freeFocus()
keyboardController?.hide()
onContinueClicked(innerValue.text)
} else {
isError = true
}
}
Box(
modifier = Modifier
.windowInsetsPadding(WindowInsets.navigationBars)
.imePadding()
//.background(color = colorResource(id = R.color.black))
.fillMaxSize()
) {
Column {
Spacer(modifier = Modifier.height(148.dp))
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
text = stringResource(R.string.onboarding_email_add_title),
color = colorResource(id = R.color.text_white),
style = HeadlineTitleSemibold,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(8.dp))
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
text = stringResource(R.string.onboarding_email_add_description),
style = UXBody,
color = colorResource(id = R.color.text_white),
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(32.dp))
OutlinedTextField(
value = innerValue,
onValueChange = { input ->
innerValue = input
isError = false
},
shape = RoundedCornerShape(size = 16.dp),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp)
.focusRequester(focusRequester),
placeholder = {
Text(
text = stringResource(id = R.string.onboarding_enter_email),
style = PreviewTitle1Regular,
color = colorResource(id = R.color.text_tertiary)
)
},
textStyle = PreviewTitle1Regular.copy(
color = Color(0xFFC2C2C2)
),
singleLine = true,
isError = isError,
supportingText = {
if (isError) {
Text(
text = stringResource(id = R.string.onboarding_email_error),
color = colorResource(id = R.color.palette_system_red),
style = Caption1Regular
)
}
},
colors = TextFieldDefaults.colors(
disabledTextColor = colorResource(id = R.color.text_primary),
cursorColor = Color(0xFFC2C2C2),
focusedContainerColor = Color(0xFF212121),
unfocusedContainerColor = Color(0xFF212121),
errorContainerColor = Color(0xFF212121),
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
errorIndicatorColor = Color.Transparent
),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions {
validateAndSubmit()
}
)
Spacer(modifier = Modifier.height(32.dp))
}
Image(
modifier = Modifier
.align(Alignment.TopStart)
.padding(top = 16.dp, start = 9.dp)
.noRippleClickable {
onBackClicked()
},
painter = painterResource(id = R.drawable.ic_back_onboarding_32),
contentDescription = stringResource(R.string.content_description_back_button_icon)
)
Column(
modifier = Modifier
.fillMaxWidth()
.padding(
start = 20.dp,
end = 20.dp,
bottom = 20.dp
)
.align(Alignment.BottomCenter)
) {
OnBoardingButtonPrimary(
text = stringResource(id = R.string.onboarding_button_continue),
onClick = {
validateAndSubmit()
},
size = ButtonSize.Large,
modifier = Modifier.fillMaxWidth(),
isLoading = isLoading,
enabled = innerValue.text.isNotEmpty()
)
Spacer(modifier = Modifier.height(8.dp))
OnBoardingButtonSecondary(
text = stringResource(id = R.string.onboarding_button_skip),
onClick = {
onSkipClicked().also {
focusRequester.freeFocus()
}
},
textColor = colorResource(id = R.color.text_white),
size = ButtonSize.Large,
modifier = Modifier.fillMaxWidth(),
)
}
}
}
@DefaultPreviews
@Composable
private fun SetProfileNameScreenPreview() {
OnboardingEmailScreen(
onContinueClicked = {},
onBackClicked = {},
onSkipClicked = {},
isLoading = false
)
}

View file

@ -42,7 +42,6 @@ import com.anytypeio.anytype.core_ui.extensions.conditional
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
import com.anytypeio.anytype.core_ui.views.BodyRegular
import com.anytypeio.anytype.core_ui.views.ButtonSize
import com.anytypeio.anytype.core_ui.views.Caption1Regular
import com.anytypeio.anytype.core_ui.views.HeadlineHeading
import com.anytypeio.anytype.core_ui.views.HeadlineOnBoardingDescription
import com.anytypeio.anytype.core_ui.views.OnBoardingButtonPrimary

View file

@ -45,12 +45,13 @@ fun SetProfileNameWrapper(
viewModel: OnboardingSetProfileNameViewModel,
onBackClicked: () -> Unit,
) {
val defaultSpaceName = stringResource(id = R.string.onboarding_my_first_space)
val name = remember { mutableStateOf("") }
SetProfileNameScreen(
onNextClicked = { name ->
onNextClicked = { inputName ->
name.value = inputName
viewModel.onNextClicked(
name = name,
spaceName = defaultSpaceName
name = inputName
)
},
isLoading = viewModel.state

View file

@ -550,7 +550,8 @@ sealed class Command {
data class Finalize(val name: String, val nameType: NameServiceNameType) : Membership()
data class GetVerificationEmail(
val email: String,
val subscribeToNewsletter: Boolean
val subscribeToNewsletter: Boolean,
val isFromOnboarding: Boolean
) : Membership()
data class VerifyEmailCode(val code: String) : Membership()

View file

@ -11,12 +11,12 @@ val OnboardingSubtitleColor = Color(0xFF505050)
val OnBoardingTextPrimaryColor = Color(0xFFF3F2EC)
val OnBoardingTextSecondaryColor = Color(0x80F3F2EC)
val ColorButtonPrimaryActive = Color(0xFF252525)
val ColorButtonPrimaryActive = Color(0xFF3A3A3A)
val ColorButtonPrimaryPressed = Color(0xFF464646)
val ColorButtonPrimaryText = Color(0xFFF2F3EC)
val ColorButtonPrimaryInactive = Color(0xFF1F1E1D)
val ColorButtonPrimaryInactiveText = Color(0xFF64635B)
val ColorButtonPrimaryInactive = Color(0xFF1F1F1F)
val ColorButtonPrimaryInactiveText = Color(0xFF646464)
val ColorButtonSecondaryActive = Color.Transparent
val ColorButtonSecondaryPressed = Color(0xFF1F1E1C)

View file

@ -328,4 +328,14 @@ val ModalTitle = TextStyle(
val AvatarTitle = TextStyle(
fontFamily = fontInterRegular,
fontWeight = FontWeight.W600
)
)
//Content/Headlines/Title Semibold
val HeadlineTitleSemibold =
TextStyle(
fontFamily = fontInterSemibold,
fontWeight = FontWeight.W600,
fontSize = 28.sp,
lineHeight = 32.sp,
letterSpacing = (-0.017).em
)

View file

@ -14,13 +14,15 @@ class SetMembershipEmail @Inject constructor(
override suspend fun doWork(params: Params) {
val command = Command.Membership.GetVerificationEmail(
email = params.email,
subscribeToNewsletter = params.subscribeToNewsletter
subscribeToNewsletter = params.subscribeToNewsletter,
isFromOnboarding = params.isFromOnboarding
)
repo.membershipGetVerificationEmail(command)
}
data class Params(
val email: String,
val subscribeToNewsletter: Boolean
val subscribeToNewsletter: Boolean,
val isFromOnboarding: Boolean = false
)
}

View file

@ -9,4 +9,5 @@ interface StringResourceProvider {
fun getUntitledObjectTitle(): String
fun getSetOfObjectsTitle(): String
fun getPropertiesFormatPrettyString(format: RelationFormat): String
fun getDefaultSpaceName(): String
}

View file

@ -1132,8 +1132,6 @@
<string name="onboarding_key_skip">Skip</string>
<string name="onboarding_key_not_now">Not now</string>
<string name="onboarding_key_copy">Copy to clipboard</string>
<string name="onboarding_set_your_name_title">Set your name</string>
<string name="onboarding_soul_creation_description">Only seen by people you share something with. There is no central registry of these names.</string>
<string name="onboarding_soul_creation_placeholder">Anytype Identity</string>
<string name="onboarding_soul_creation">Creating your Identity…</string>
<string name="onboarding_type_your_key">Type your recovery phrase</string>
@ -2044,4 +2042,13 @@ Please provide specific details of your needs here.</string>
<string name="space_properties_screen_menu_move_to_bin">Move to bin</string>
<string name="onboarding_error_while_creating_account_space_is_missing">Error while creating account: space is missing</string>
<string name="onboarding_set_your_name_title">Add Your Name</string>
<string name="onboarding_soul_creation_description">Only seen by people you share something with. There is no central registry for these names.</string>
<string name="onboarding_email_add_title">Stay in the loop</string>
<string name="onboarding_email_add_description">Wed love to share tips, tricks and product updates with you. Your email is never linked to your identity. We wont share your data. Ever.</string>
<string name="onboarding_enter_email">Enter your email</string>
<string name="onboarding_button_continue">Continue</string>
<string name="onboarding_button_skip">Skip</string>
<string name="onboarding_email_error">Incorrect email</string>
</resources>

View file

@ -2663,7 +2663,8 @@ class Middleware @Inject constructor(
fun membershipGetVerificationEmail(command: Command.Membership.GetVerificationEmail) {
val request = Rpc.Membership.GetVerificationEmail.Request(
email = command.email,
subscribeToNewsletter = command.subscribeToNewsletter
subscribeToNewsletter = command.subscribeToNewsletter,
isOnboardingList = command.isFromOnboarding
)
logRequestIfDebug(request)
val (response, time) = measureTimedValue { service.membershipGetVerificationEmail(request) }

View file

@ -19,9 +19,12 @@ import com.anytypeio.anytype.domain.device.PathProvider
import com.anytypeio.anytype.domain.misc.LocaleProvider
import com.anytypeio.anytype.domain.`object`.ImportGetStartedUseCase
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
import com.anytypeio.anytype.domain.payments.SetMembershipEmail
import com.anytypeio.anytype.domain.resources.StringResourceProvider
import com.anytypeio.anytype.domain.spaces.SetSpaceDetails
import com.anytypeio.anytype.domain.subscriptions.GlobalSubscriptionManager
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.BuildConfig
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.extension.proceedWithAccountEvent
import com.anytypeio.anytype.presentation.extension.sendAnalyticsOnboardingScreenEvent
@ -46,7 +49,9 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
private val crashReporter: CrashReporter,
private val localeProvider: LocaleProvider,
private val globalSubscriptionManager: GlobalSubscriptionManager,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val stringProvider: StringResourceProvider,
private val setMembershipEmail: SetMembershipEmail,
) : BaseViewModel() {
init {
@ -62,22 +67,23 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
val navigation = MutableSharedFlow<Navigation>()
fun onNextClicked(
name: String,
spaceName: String
name: String
) {
if (state.value !is ScreenState.Loading) {
proceedWithCreatingWallet(
name = name,
spaceName = spaceName
)
viewModelScope.launch {
navigation.emit(
Navigation.NavigateToAddEmailScreen(
name = name
)
)
}
} else {
sendToast(LOADING_MSG)
}
}
private fun proceedWithCreatingWallet(
name: String,
spaceName: String
name: String
) {
state.value = ScreenState.Loading
setupWallet.invoke(
@ -92,8 +98,7 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
},
fnR = {
proceedWithCreatingAccount(
name = name,
spaceName = spaceName
name = name
)
}
)
@ -101,9 +106,9 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
}
private fun proceedWithCreatingAccount(
name: String,
spaceName: String
name: String
) {
val spaceName = stringProvider.getDefaultSpaceName()
val startTime = System.currentTimeMillis()
val params = CreateAccount.Params(
name = name,
@ -248,6 +253,53 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
}
}
//region Email screen
fun onEmailContinueClicked(
email: String,
name: String,
) {
proceedWithSettingEmail(email = email)
if (state.value !is ScreenState.Loading) {
proceedWithCreatingWallet(
name = name
)
} else {
sendToast(LOADING_MSG)
}
}
fun onEmailSkippedClicked(
name: String
) {
if (state.value !is ScreenState.Loading) {
proceedWithCreatingWallet(
name = name
)
} else {
sendToast(LOADING_MSG)
}
}
private fun proceedWithSettingEmail(email: String) {
val params = SetMembershipEmail.Params(
email = email,
subscribeToNewsletter = false,
isFromOnboarding = true
)
viewModelScope.launch {
setMembershipEmail.async(params).fold(
onSuccess = { Timber.d("Email set") },
onFailure = { error ->
if (BuildConfig.DEBUG) {
sendToast("Error setting email")
}
Timber.e("Error setting email: $error")
}
)
}
}
//endregion
class Factory @Inject constructor(
private val setObjectDetails: SetObjectDetails,
private val setSpaceDetails: SetSpaceDetails,
@ -261,7 +313,9 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
private val crashReporter: CrashReporter,
private val localeProvider: LocaleProvider,
private val globalSubscriptionManager: GlobalSubscriptionManager,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val stringProvider: StringResourceProvider,
private val setMembershipEmail: SetMembershipEmail
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -278,7 +332,9 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
crashReporter = crashReporter,
localeProvider = localeProvider,
globalSubscriptionManager = globalSubscriptionManager,
spaceManager = spaceManager
spaceManager = spaceManager,
stringProvider = stringProvider,
setMembershipEmail = setMembershipEmail
) as T
}
}
@ -292,6 +348,9 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
sealed class Navigation {
data class NavigateToMnemonic(val space: SpaceId, val startingObject: Id?): Navigation()
data class NavigateToAddEmailScreen(
val name: String
) : Navigation()
data object GoBack: Navigation()
}

View file

@ -51,4 +51,8 @@ class StringResourceProviderImpl @Inject constructor(private val context: Contex
RelationFormat.UNDEFINED -> context.getString(R.string.undefined)
}
}
override fun getDefaultSpaceName(): String {
return context.getString(R.string.onboarding_my_first_space)
}
}