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

DROID-3554 Use cases | Enhancement | Automatically open a specific object when a new space is created or account is created (#2363)

This commit is contained in:
Evgenii Kozlov 2025-04-28 15:22:56 +02:00
parent fd10386b90
commit bcbb8368e7
17 changed files with 219 additions and 57 deletions

View file

@ -30,6 +30,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
@ -48,6 +49,7 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.os.bundleOf
@ -58,17 +60,21 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
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
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
@ -83,6 +89,8 @@ import com.anytypeio.anytype.presentation.onboarding.OnboardingViewModel
import com.anytypeio.anytype.presentation.onboarding.login.OnboardingMnemonicLoginViewModel
import com.anytypeio.anytype.presentation.onboarding.signup.OnboardingMnemonicViewModel
import com.anytypeio.anytype.presentation.onboarding.signup.OnboardingSetProfileNameViewModel
import com.anytypeio.anytype.ui.editor.EditorFragment
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
@ -285,7 +293,15 @@ class OnboardingFragment : Fragment() {
Recovery(navController)
}
composable(
route = OnboardingNavigation.mnemonic,
route = "${OnboardingNavigation.mnemonic}?$ONBOARDING_SPACE_PARAM={$ONBOARDING_SPACE_PARAM}&$ONBOARDING_STARTING_OBJECT_PARAM={$ONBOARDING_STARTING_OBJECT_PARAM}",
arguments = listOf(
navArgument(ONBOARDING_SPACE_PARAM) { type = NavType.StringType },
navArgument(ONBOARDING_STARTING_OBJECT_PARAM) {
type = NavType.StringType
nullable = true
defaultValue = null
}
),
enterTransition = {
when (initialState.destination.route) {
OnboardingNavigation.setProfileName -> {
@ -311,9 +327,25 @@ class OnboardingFragment : Fragment() {
backButtonCallback.value = {
// Do nothing
}
Mnemonic(
mnemonicColorPalette = mnemonicColorPalette
)
val spaceId = it.arguments?.getString(ONBOARDING_SPACE_PARAM)
val startingObjectId = it.arguments?.getString(ONBOARDING_STARTING_OBJECT_PARAM)
if (!spaceId.isNullOrEmpty()) {
Mnemonic(
mnemonicColorPalette = mnemonicColorPalette,
space = spaceId,
startingObject = startingObjectId
)
} else {
Box(
modifier = Modifier.fillMaxSize()
) {
Text(
text = stringResource(R.string.onboarding_error_while_creating_account_space_is_missing),
modifier = Modifier.align(Alignment.Center),
textAlign = TextAlign.Center
)
}
}
BackHandler {
toast("You're just one step away from finishing this registration.")
}
@ -511,8 +543,13 @@ class OnboardingFragment : Fragment() {
focusManager.clearFocus(force = true)
delay(KEYBOARD_HIDE_DELAY)
}
val space = command.space
val startingObject = command.startingObject
navController.navigate(
route = OnboardingNavigation.mnemonic
route = buildString {
append("${OnboardingNavigation.mnemonic}?$ONBOARDING_SPACE_PARAM=${space.id}")
startingObject?.let { append("&$ONBOARDING_STARTING_OBJECT_PARAM=${it}") }
}
)
}
is OnboardingSetProfileNameViewModel.Navigation.GoBack -> {
@ -533,11 +570,15 @@ class OnboardingFragment : Fragment() {
@Composable
private fun Mnemonic(
mnemonicColorPalette: List<Color>
mnemonicColorPalette: List<Color>,
space: Id,
startingObject: Id?
) {
val component = componentManager().onboardingMnemonicComponent
val vm = daggerViewModel { component.get().getViewModel() }
MnemonicPhraseScreenWrapper(
space = space,
startingObject = startingObject,
viewModel = vm,
copyMnemonicToClipboard = ::copyMnemonicToClipboard,
vm = vm,
@ -559,6 +600,30 @@ class OnboardingFragment : Fragment() {
Timber.e(it, "Error while navigation to vault")
}
}
is OnboardingMnemonicViewModel.Command.OpenStartingObject -> {
runCatching {
findNavController().navigate(
R.id.actionOpenVault,
VaultFragment.args(deepLink)
)
findNavController().navigate(
R.id.actionOpenSpaceFromVault,
HomeScreenFragment.args(
space = command.space.id,
deeplink = null
)
)
findNavController().navigate(
R.id.objectNavigation,
EditorFragment.args(
ctx = command.startingObject,
space = command.space.id,
)
)
}.onFailure {
Timber.e(it, "Error while navigation to vault")
}
}
}
}
}
@ -704,6 +769,9 @@ class OnboardingFragment : Fragment() {
ONBOARDING_DEEP_LINK_KEY to deepLink
)
private const val ONBOARDING_DEEP_LINK_KEY = "arg.onboarding.deep-link-key"
private const val ONBOARDING_SPACE_PARAM = "space"
private const val ONBOARDING_STARTING_OBJECT_PARAM = "startingObject"
}
}

View file

@ -33,6 +33,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_ui.ColorBackgroundField
import com.anytypeio.anytype.core_ui.ColorButtonRegular
import com.anytypeio.anytype.core_ui.OnBoardingTextPrimaryColor
@ -52,6 +53,8 @@ import com.anytypeio.anytype.ui.onboarding.MnemonicStub
@Composable
fun MnemonicPhraseScreenWrapper(
space: Id,
startingObject: Id?,
viewModel: OnboardingMnemonicViewModel,
copyMnemonicToClipboard: (String) -> Unit,
vm: OnboardingMnemonicViewModel,
@ -61,10 +64,20 @@ fun MnemonicPhraseScreenWrapper(
MnemonicPhraseScreen(
state = state,
reviewMnemonic = { viewModel.openMnemonic() },
onCheckLaterClicked = vm::onCheckLaterClicked,
onCheckLaterClicked = {
vm.onCheckLaterClicked(
space = space,
startingObject = startingObject
)
},
copyMnemonicToClipboard = copyMnemonicToClipboard,
mnemonicColorPalette = mnemonicColorPalette,
onGoToAppClicked = vm::onGoToTheAppClicked
onGoToAppClicked = {
vm.onGoToTheAppClicked(
space = space,
startingObject = startingObject
)
}
)
}

View file

@ -16,6 +16,7 @@ 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.spaces.CreateSpaceViewModel
import com.anytypeio.anytype.ui.editor.EditorFragment
import com.anytypeio.anytype.ui.home.HomeScreenFragment
import com.anytypeio.anytype.ui.settings.typography
import javax.inject.Inject
@ -63,6 +64,17 @@ class CreateSpaceFragment : BaseBottomSheetComposeFragment() {
deeplink = null
)
)
command.startingObject
?.takeIf { it.isNotEmpty() }
?.let { startingObject ->
findNavController().navigate(
R.id.objectNavigation,
EditorFragment.args(
ctx = startingObject,
space = command.space.id
)
)
}
}.onFailure {
Timber.e(it, "Error while exiting to vault or opening created space")
}

View file

@ -482,6 +482,7 @@
app:enterAnim="@anim/fade_in"
app:popUpTo="@id/authStartScreen"
app:popUpToInclusive="true" />
</navigation>
<fragment

View file

@ -478,7 +478,18 @@ sealed class Command {
val details: Struct,
val withChat: Boolean,
val shouldApplyEmptyUseCase: Boolean
)
) {
data class Result(
val space: SpaceId,
val startingObject: Id? = null
)
}
data object ImportUseCase {
data class Result(
val startingObject: Id? = null
)
}
data class CreateObjectType(
val details: Struct,

View file

@ -244,7 +244,7 @@ class BlockDataRepository(
Undo.Result.Exhausted
}
override suspend fun importGetStartedUseCase(space: Id) = remote.importGetStartedUseCase(space = space)
override suspend fun importGetStartedUseCase(space: Id): Command.ImportUseCase.Result = remote.importGetStartedUseCase(space = space)
override suspend fun redo(
command: Command.Redo
@ -761,7 +761,7 @@ class BlockDataRepository(
remote.deleteSpace(space)
}
override suspend fun createWorkspace(command: Command.CreateSpace): Id = remote.createWorkspace(
override suspend fun createWorkspace(command: Command.CreateSpace): Command.CreateSpace.Result = remote.createWorkspace(
command = command
)

View file

@ -89,7 +89,7 @@ interface BlockRemote {
suspend fun createBookmarkObject(space: Id, url: Url, details: Struct): Id
suspend fun fetchBookmarkObject(ctx: Id, url: Url)
suspend fun undo(command: Command.Undo): Payload
suspend fun importGetStartedUseCase(space: Id)
suspend fun importGetStartedUseCase(space: Id) : Command.ImportUseCase.Result
suspend fun redo(command: Command.Redo): Payload
suspend fun turnIntoDocument(command: Command.TurnIntoDocument): List<Id>
suspend fun paste(command: Command.Paste): Response.Clipboard.Paste
@ -340,7 +340,7 @@ interface BlockRemote {
suspend fun setSpaceDetails(space: SpaceId, details: Struct)
suspend fun deleteSpace(space: SpaceId)
suspend fun createWorkspace(command: Command.CreateSpace): Id
suspend fun createWorkspace(command: Command.CreateSpace): Command.CreateSpace.Result
suspend fun getSpaceConfig(space: Id): Config

View file

@ -147,7 +147,7 @@ interface BlockRepository {
suspend fun undo(command: Command.Undo): Undo.Result
suspend fun importGetStartedUseCase(space: Id)
suspend fun importGetStartedUseCase(space: Id): Command.ImportUseCase.Result
suspend fun redo(command: Command.Redo): Redo.Result
@ -392,7 +392,7 @@ interface BlockRepository {
): Payload
suspend fun deleteSpace(space: SpaceId)
suspend fun createWorkspace(command: Command.CreateSpace): Id
suspend fun createWorkspace(command: Command.CreateSpace): Command.CreateSpace.Result
suspend fun getSpaceConfig(space: Id): Config
suspend fun addObjectListToSpace(objects: List<Id>, space: Id) : List<Id>
suspend fun addObjectToSpace(command: Command.AddObjectToSpace) : Pair<Id, Struct?>

View file

@ -1,5 +1,6 @@
package com.anytypeio.anytype.domain.`object`
import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.ResultInteractor
@ -8,10 +9,10 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
class ImportGetStartedUseCase(
private val repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
): ResultInteractor<ImportGetStartedUseCase.Params, Unit>(dispatchers.io) {
): ResultInteractor<ImportGetStartedUseCase.Params, Command.ImportUseCase.Result>(dispatchers.io) {
override suspend fun doWork(params: Params) {
repo.importGetStartedUseCase(params.space)
override suspend fun doWork(params: Params): Command.ImportUseCase.Result {
return repo.importGetStartedUseCase(params.space)
}
data class Params(val space: Id)

View file

@ -11,9 +11,9 @@ import javax.inject.Inject
class CreateSpace @Inject constructor(
private val repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<CreateSpace.Params, Id>(dispatchers.io) {
) : ResultInteractor<CreateSpace.Params, Command.CreateSpace.Result>(dispatchers.io) {
override suspend fun doWork(params: Params): Id = repo.createWorkspace(
override suspend fun doWork(params: Params) = repo.createWorkspace(
command = Command.CreateSpace(
details = params.details,
withChat = params.withChat,

View file

@ -28,13 +28,11 @@ import com.anytypeio.anytype.gallery_experience.models.GalleryInstallationNaviga
import com.anytypeio.anytype.gallery_experience.models.GalleryInstallationSpacesState
import com.anytypeio.anytype.gallery_experience.models.GalleryInstallationState
import com.anytypeio.anytype.gallery_experience.models.GallerySpaceView
import com.anytypeio.anytype.presentation.spaces.CreateSpaceViewModel.Companion.MAX_SPACE_COUNT_WITH_GET_STARTED_USE_CASE
import com.anytypeio.anytype.presentation.spaces.SelectSpaceViewModel
import com.anytypeio.anytype.presentation.spaces.SpaceGradientProvider
import com.anytypeio.anytype.presentation.spaces.spaceIcon
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import timber.log.Timber
@ -132,12 +130,11 @@ class GalleryInstallationViewModel(
Relations.NAME to manifestInfo.title,
Relations.ICON_OPTION to spaceGradientProvider.randomId().toDouble()
),
shouldApplyEmptyUseCase = spacesViewState.value.spaces.count { item ->
item.obj.isActive
} >= MAX_SPACE_COUNT_WITH_GET_STARTED_USE_CASE
shouldApplyEmptyUseCase = true
)
createSpace.async(params).fold(
onSuccess = { space ->
onSuccess = { result ->
val space = result.space.id
Timber.d("CreateSpace success, space: $space")
analytics.sendEvent(
eventName = EventsDictionary.clickGalleryInstallSpace,

View file

@ -2042,5 +2042,6 @@ Please provide specific details of your needs here.</string>
<string name="space_properties_screen_section_my_types">My Properties</string>
<string name="space_properties_screen_section_system_types">System Properties</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>
</resources>

View file

@ -214,7 +214,7 @@ class BlockMiddleware(
override suspend fun importGetStartedUseCase(
space: Id
) = middleware.objectImportUseCaseGetStarted(
): Command.ImportUseCase.Result = middleware.objectImportUseCaseGetStarted(
space = space
)
@ -728,7 +728,7 @@ class BlockMiddleware(
middleware.spaceDelete(space)
}
override suspend fun createWorkspace(command: Command.CreateSpace): Id = middleware.workspaceCreate(
override suspend fun createWorkspace(command: Command.CreateSpace): Command.CreateSpace.Result = middleware.workspaceCreate(
command = command
)

View file

@ -1598,14 +1598,17 @@ class Middleware @Inject constructor(
}
@Throws(Exception::class)
fun objectImportUseCaseGetStarted(space: Id) {
fun objectImportUseCaseGetStarted(space: Id) : Command.ImportUseCase.Result {
val request = Rpc.Object.ImportUseCase.Request(
spaceId = space,
useCase = Rpc.Object.ImportUseCase.Request.UseCase.GET_STARTED
useCase = Rpc.Object.ImportUseCase.Request.UseCase.GET_STARTED_MOBILE
)
logRequestIfDebug(request)
val (response, time) = measureTimedValue { service.objectImportUseCase(request) }
logResponseIfDebug(response, time)
return Command.ImportUseCase.Result(
startingObject = response.startingObjectId.ifEmpty { null }
)
}
@Throws(Exception::class)
@ -1960,19 +1963,22 @@ class Middleware @Inject constructor(
}
@Throws(Exception::class)
fun workspaceCreate(command: Command.CreateSpace): Id {
fun workspaceCreate(command: Command.CreateSpace): Command.CreateSpace.Result {
val request = Rpc.Workspace.Create.Request(
details = command.details,
useCase = if (command.shouldApplyEmptyUseCase)
Rpc.Object.ImportUseCase.Request.UseCase.EMPTY
Rpc.Object.ImportUseCase.Request.UseCase.EMPTY_MOBILE
else
Rpc.Object.ImportUseCase.Request.UseCase.GET_STARTED,
Rpc.Object.ImportUseCase.Request.UseCase.GET_STARTED_MOBILE,
withChat = command.withChat
)
logRequestIfDebug(request)
val (response, time) = measureTimedValue { service.workspaceCreate(request) }
logResponseIfDebug(response, time)
return response.spaceId
return Command.CreateSpace.Result(
space = SpaceId(response.spaceId),
startingObject = response.startingObjectId.ifEmpty { null }
)
}
@Throws(Exception::class)

View file

@ -5,6 +5,8 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.analytics.base.EventsDictionary
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.auth.interactor.GetMnemonic
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.presentation.extension.sendAnalyticsOnboardingClickEvent
@ -46,7 +48,10 @@ class OnboardingMnemonicViewModel @Inject constructor(
)
}
fun onCheckLaterClicked() {
fun onCheckLaterClicked(
space: Id,
startingObject: Id?,
) {
viewModelScope.sendAnalyticsOnboardingClickEvent(
analytics = analytics,
type = EventsDictionary.ClickOnboardingButton.CHECK_LATER,
@ -61,11 +66,23 @@ class OnboardingMnemonicViewModel @Inject constructor(
} else {
Timber.w("config was missing before the end of onboarding")
}
commands.emit(Command.OpenVault)
if (!startingObject.isNullOrEmpty()) {
commands.emit(
Command.OpenStartingObject(
space = SpaceId(space),
startingObject = startingObject
)
)
} else {
commands.emit(Command.OpenVault)
}
}
}
fun onGoToTheAppClicked() {
fun onGoToTheAppClicked(
space: Id,
startingObject: Id?,
) {
viewModelScope.launch {
val config = configStorage.getOrNull()
if (config != null) {
@ -75,7 +92,16 @@ class OnboardingMnemonicViewModel @Inject constructor(
} else {
Timber.w("config was missing before the end of onboarding")
}
commands.emit(Command.OpenVault)
if (!startingObject.isNullOrEmpty()) {
commands.emit(
Command.OpenStartingObject(
space = SpaceId(space),
startingObject = startingObject
)
)
} else {
commands.emit(Command.OpenVault)
}
}
}
@ -115,5 +141,9 @@ class OnboardingMnemonicViewModel @Inject constructor(
sealed class Command {
data object OpenVault : Command()
data class OpenStartingObject(
val space: SpaceId,
val startingObject: Id
) : Command()
}
}

View file

@ -21,6 +21,7 @@ import com.anytypeio.anytype.domain.`object`.ImportGetStartedUseCase
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
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.common.BaseViewModel
import com.anytypeio.anytype.presentation.extension.proceedWithAccountEvent
import com.anytypeio.anytype.presentation.extension.sendAnalyticsOnboardingScreenEvent
@ -44,7 +45,8 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
private val spaceGradientProvider: SpaceGradientProvider,
private val crashReporter: CrashReporter,
private val localeProvider: LocaleProvider,
private val globalSubscriptionManager: GlobalSubscriptionManager
private val globalSubscriptionManager: GlobalSubscriptionManager,
private val spaceManager: SpaceManager
) : BaseViewModel() {
init {
@ -133,6 +135,9 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
val config = configStorage.getOrNull()
if (config != null) {
crashReporter.setUser(config.analytics)
spaceManager.set(config.space).onFailure {
Timber.e(it, "Error while setting current space during sign-up onboarding")
}
setupGlobalSubscriptions()
proceedWithSettingUpMobileUseCase(
space = config.space,
@ -153,7 +158,8 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
private fun proceedWithSettingAccountName(
name: String,
spaceName: String
spaceName: String,
startingObjectId: Id?
) {
val config = configStorage.getOrNull()
if (config != null) {
@ -176,13 +182,23 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
).fold(
onFailure = {
Timber.e(it, "Error while setting profile name details")
navigation.emit(Navigation.NavigateToMnemonic)
navigation.emit(
Navigation.NavigateToMnemonic(
space = SpaceId(config.space),
startingObject = startingObjectId
)
)
// Workaround for leaving screen in loading state to wait screen transition
delay(LOADING_AFTER_SUCCESS_DELAY)
state.value = ScreenState.Success
},
onSuccess = {
navigation.emit(Navigation.NavigateToMnemonic)
navigation.emit(
Navigation.NavigateToMnemonic(
space = SpaceId(config.space),
startingObject = startingObjectId
)
)
// Workaround for leaving screen in loading state to wait screen transition
delay(LOADING_AFTER_SUCCESS_DELAY)
state.value = ScreenState.Success
@ -217,13 +233,15 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
onFailure = {
proceedWithSettingAccountName(
name = name,
spaceName = spaceName
spaceName = spaceName,
startingObjectId = null
)
},
onSuccess = {
onSuccess = { result ->
proceedWithSettingAccountName(
name = name,
spaceName = spaceName
spaceName = spaceName,
startingObjectId = result.startingObject
)
}
)
@ -242,7 +260,8 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
private val importGetStartedUseCase: ImportGetStartedUseCase,
private val crashReporter: CrashReporter,
private val localeProvider: LocaleProvider,
private val globalSubscriptionManager: GlobalSubscriptionManager
private val globalSubscriptionManager: GlobalSubscriptionManager,
private val spaceManager: SpaceManager
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -258,7 +277,8 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
spaceGradientProvider = spaceGradientProvider,
crashReporter = crashReporter,
localeProvider = localeProvider,
globalSubscriptionManager = globalSubscriptionManager
globalSubscriptionManager = globalSubscriptionManager,
spaceManager = spaceManager
) as T
}
}
@ -271,7 +291,7 @@ class OnboardingSetProfileNameViewModel @Inject constructor(
}
sealed class Navigation {
data object NavigateToMnemonic: Navigation()
data class NavigateToMnemonic(val space: SpaceId, val startingObject: Id?): Navigation()
data object GoBack: Navigation()
}

View file

@ -67,13 +67,14 @@ class CreateSpaceViewModel(
Relations.NAME to name,
Relations.ICON_OPTION to spaceIconView.value.color.index.toDouble()
),
shouldApplyEmptyUseCase = numberOfActiveSpaces >= MAX_SPACE_COUNT_WITH_GET_STARTED_USE_CASE,
shouldApplyEmptyUseCase = true,
withChat = BuildConfig.DEBUG && isSpaceLevelChatSwitchChecked
)
).collect { result ->
result.fold(
onLoading = { isInProgress.value = true },
onSuccess = { space: Id ->
onSuccess = { response ->
val space = response.space.id
analytics.sendEvent(
eventName = EventsDictionary.createSpace,
props = Props(
@ -83,7 +84,12 @@ class CreateSpaceViewModel(
setNewSpaceAsCurrentSpace(space)
Timber.d("Successfully created space: $space").also {
isInProgress.value = false
commands.emit(Command.SwitchSpace(space = Space(space)))
commands.emit(
Command.SwitchSpace(
space = Space(space),
startingObject = response.startingObject
)
)
}
},
onFailure = {
@ -130,12 +136,8 @@ class CreateSpaceViewModel(
sealed class Command {
data class SwitchSpace(
val space: Space
val space: Space,
val startingObject: Id?
): Command()
}
companion object {
// Always applying "empty" use-case when creating new space
const val MAX_SPACE_COUNT_WITH_GET_STARTED_USE_CASE = 0
}
}