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

Feature | Reopen the last opened object or set on application start (#1851)

This commit is contained in:
Evgenii Kozlov 2021-10-14 14:51:16 +03:00 committed by GitHub
parent ecfe6baeaf
commit ad421e3fe6
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 356 additions and 26 deletions

View file

@ -1,5 +1,20 @@
# Change log for Android @Anytype app.
## Version 0.3.3 (WIP)
### New features & enhancements 🚀
* App: Restoring the last opened object or the last opened set on application start (#1851)
* App: Drafts without any history will be deleted after close (#1833)
* Editor | Drag & drop (position above, below or inside) (#1848)
* Sets | Grid as fallback view: views not supported on Android can be seen as grid (#1850)
### Design & UX 🔳
### Fixes & tech 🚒
## Version 0.3.2
### New features & enhancements 🚀

View file

@ -6,6 +6,7 @@ import androidx.fragment.app.testing.launchFragmentInContainer
import com.anytypeio.anytype.R
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_models.*
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.block.interactor.UpdateText
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.Gateway
@ -46,6 +47,10 @@ abstract class TestObjectSetSetup {
@Mock
lateinit var repo: BlockRepository
@Mock
lateinit var auth: AuthRepository
@Mock
lateinit var gateway: Gateway
@Mock
@ -88,7 +93,7 @@ abstract class TestObjectSetSetup {
addDataViewRelation = AddNewRelationToDataView(repo)
updateText = UpdateText(repo)
openObjectSet = OpenObjectSet(repo)
openObjectSet = OpenObjectSet(repo, auth)
createDataViewRecord = CreateDataViewRecord(repo)
updateDataViewRecord = UpdateDataViewRecord(repo)
updateDataViewViewer = UpdateDataViewViewer(repo)

View file

@ -4,6 +4,7 @@ import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider
import com.anytypeio.anytype.domain.auth.interactor.GetProfile
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.block.interactor.Move
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.GetConfig
@ -87,9 +88,11 @@ object HomeDashboardModule {
@Provides
@PerScreen
fun provideOpenDashboardUseCase(
repo: BlockRepository
repo: BlockRepository,
auth: AuthRepository
): OpenDashboard = OpenDashboard(
repo = repo
repo = repo,
auth = auth
)
@JvmStatic

View file

@ -12,6 +12,7 @@ import com.anytypeio.anytype.di.feature.relations.RelationCreateFromScratchForOb
import com.anytypeio.anytype.di.feature.relations.RelationCreateFromScratchForObjectSubComponent
import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.block.UpdateDivider
import com.anytypeio.anytype.domain.block.interactor.*
import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
@ -297,9 +298,11 @@ object EditorUseCaseModule {
@Provides
@PerScreen
fun provideOpenPageUseCase(
repo: BlockRepository
repo: BlockRepository,
auth: AuthRepository
): OpenPage = OpenPage(
repo = repo
repo = repo,
auth = auth
)
@JvmStatic

View file

@ -13,6 +13,7 @@ import com.anytypeio.anytype.di.feature.sets.CreateFilterSubComponent
import com.anytypeio.anytype.di.feature.sets.ModifyFilterSubComponent
import com.anytypeio.anytype.di.feature.sets.SelectFilterRelationSubComponent
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.block.interactor.UpdateText
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.dataview.interactor.*
@ -118,7 +119,10 @@ object ObjectSetModule {
@JvmStatic
@Provides
@PerScreen
fun provideOpenObjectSetUseCase(repo: BlockRepository): OpenObjectSet = OpenObjectSet(repo)
fun provideOpenObjectSetUseCase(
repo: BlockRepository,
auth: AuthRepository
): OpenObjectSet = OpenObjectSet(repo = repo, auth = auth)
@JvmStatic
@Provides

View file

@ -4,6 +4,7 @@ import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider
import com.anytypeio.anytype.domain.auth.interactor.CheckAuthorizationStatus
import com.anytypeio.anytype.domain.auth.interactor.GetLastOpenedObject
import com.anytypeio.anytype.domain.auth.interactor.LaunchAccount
import com.anytypeio.anytype.domain.auth.interactor.LaunchWallet
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
@ -13,6 +14,7 @@ import com.anytypeio.anytype.domain.config.FlavourConfigProvider
import com.anytypeio.anytype.domain.device.PathProvider
import com.anytypeio.anytype.presentation.splash.SplashViewModelFactory
import com.anytypeio.anytype.ui.splash.SplashFragment
import com.squareup.wire.get
import dagger.Module
import dagger.Provides
import dagger.Subcomponent
@ -47,13 +49,15 @@ object SplashModule {
launchAccount: LaunchAccount,
launchWallet: LaunchWallet,
analytics: Analytics,
storeObjectTypes: StoreObjectTypes
storeObjectTypes: StoreObjectTypes,
getLastOpenedObject: GetLastOpenedObject
): SplashViewModelFactory = SplashViewModelFactory(
checkAuthorizationStatus = checkAuthorizationStatus,
launchAccount = launchAccount,
launchWallet = launchWallet,
analytics = analytics,
storeObjectTypes = storeObjectTypes
storeObjectTypes = storeObjectTypes,
getLastOpenedObject = getLastOpenedObject
)
@JvmStatic
@ -97,4 +101,15 @@ object SplashModule {
repo: BlockRepository,
objectTypesProvider: ObjectTypesProvider
) : StoreObjectTypes = StoreObjectTypes(repo, objectTypesProvider)
@JvmStatic
@Provides
@PerScreen
fun getLastOpenedObject(
repo: BlockRepository,
auth: AuthRepository
) : GetLastOpenedObject = GetLastOpenedObject(
authRepo = auth,
blockRepo = repo
)
}

View file

@ -105,6 +105,20 @@ class Navigator : AppNavigation {
)
}
override fun launchObjectFromSplash(id: Id) {
navController?.navigate(
R.id.action_splashScreen_to_objectScreen,
bundleOf(EditorFragment.ID_KEY to id),
)
}
override fun launchObjectSetFromSplash(id: Id) {
navController?.navigate(
R.id.action_splashScreen_to_objectSetScreen,
bundleOf(ObjectSetFragment.CONTEXT_ID_KEY to id),
)
}
override fun openKeychainScreen() {
navController?.navigate(R.id.action_open_keychain)
}
@ -149,11 +163,17 @@ class Navigator : AppNavigation {
}
override fun exit() {
navController?.popBackStack()
val popped = navController?.popBackStack()
if (popped == false) {
navController?.navigate(R.id.desktopScreen)
}
}
override fun exitToDesktop() {
navController?.popBackStack(R.id.desktopScreen, false)
val popped = navController?.popBackStack(R.id.desktopScreen, false)
if (popped == false) {
navController?.navigate(R.id.desktopScreen)
}
}
override fun openDebugSettings() {

View file

@ -42,6 +42,8 @@ abstract class NavigationFragment(
is Command.OpenObjectSet -> navigation.openObjectSet(command.target)
is Command.LaunchObjectSet -> navigation.launchObjectSet(command.target)
is Command.LaunchDocument -> navigation.launchDocument(command.id)
is Command.LaunchObjectFromSplash -> navigation.launchObjectFromSplash(command.target)
is Command.LaunchObjectSetFromSplash -> navigation.launchObjectSetFromSplash(command.target)
is Command.OpenDatabaseViewAddView -> navigation.openDatabaseViewAddView()
is Command.OpenEditDatabase -> navigation.openEditDatabase()
is Command.OpenKeychainScreen -> navigation.openKeychainScreen()

View file

@ -206,6 +206,24 @@
app:popExitAnim="@anim/nav_default_pop_exit_anim"
app:popUpTo="@+id/splashScreen"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_splashScreen_to_objectScreen"
app:destination="@id/objectNavigation"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim"
app:popUpTo="@+id/main_navigation"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_splashScreen_to_objectSetScreen"
app:destination="@id/dataViewNavigation"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim"
app:popUpTo="@+id/main_navigation"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_splashFragment_to_login_nav"
app:destination="@id/login_nav"

View file

@ -1,5 +1,6 @@
package com.anytypeio.anytype.data.auth.repo
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.data.auth.model.AccountEntity
interface AuthCache {
@ -16,4 +17,8 @@ interface AuthCache {
suspend fun logout()
suspend fun getAccounts(): List<AccountEntity>
suspend fun setCurrentAccount(id: String)
suspend fun saveLastOpenedObject(id: Id)
suspend fun getLastOpenedObject() : Id?
suspend fun clearLastOpenedObject()
}

View file

@ -1,5 +1,7 @@
package com.anytypeio.anytype.data.auth.repo
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.data.auth.model.AccountEntity
import com.anytypeio.anytype.data.auth.model.FlavourConfigEntity
import com.anytypeio.anytype.data.auth.model.WalletEntity
@ -69,4 +71,8 @@ class AuthCacheDataStore(private val cache: AuthCache) : AuthDataStore {
override suspend fun getVersion(): String {
throw UnsupportedOperationException()
}
override suspend fun saveLastOpenedObject(id: Id) { cache.saveLastOpenedObject(id) }
override suspend fun getLastOpenedObject(): Id? = cache.getLastOpenedObject()
override suspend fun clearLastOpenedObject() { cache.clearLastOpenedObject() }
}

View file

@ -7,6 +7,8 @@ import com.anytypeio.anytype.domain.auth.model.Account
import com.anytypeio.anytype.domain.auth.model.Wallet
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.core_models.FlavourConfig
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import kotlinx.coroutines.flow.map
class AuthDataRepository(
@ -77,4 +79,8 @@ class AuthDataRepository(
}
override suspend fun getVersion(): String = factory.remote.getVersion()
override suspend fun saveLastOpenedObjectId(id: Id) { factory.cache.saveLastOpenedObject(id) }
override suspend fun getLastOpenedObjectId(): Id? = factory.cache.getLastOpenedObject()
override suspend fun clearLastOpenedObject() { factory.cache.clearLastOpenedObject() }
}

View file

@ -1,5 +1,7 @@
package com.anytypeio.anytype.data.auth.repo
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.data.auth.model.AccountEntity
import com.anytypeio.anytype.data.auth.model.FlavourConfigEntity
import com.anytypeio.anytype.data.auth.model.WalletEntity
@ -33,4 +35,8 @@ interface AuthDataStore {
suspend fun setCurrentAccount(id: String)
suspend fun getVersion(): String
suspend fun saveLastOpenedObject(id: Id)
suspend fun getLastOpenedObject() : Id?
suspend fun clearLastOpenedObject()
}

View file

@ -1,5 +1,7 @@
package com.anytypeio.anytype.data.auth.repo
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.data.auth.model.AccountEntity
import com.anytypeio.anytype.data.auth.model.WalletEntity
@ -71,4 +73,16 @@ class AuthRemoteDataStore(
}
override suspend fun getVersion(): String = authRemote.getVersion()
override suspend fun saveLastOpenedObject(id: Id) {
throw UnsupportedOperationException()
}
override suspend fun getLastOpenedObject(): Id? {
throw UnsupportedOperationException()
}
override suspend fun clearLastOpenedObject() {
throw UnsupportedOperationException()
}
}

View file

@ -0,0 +1,15 @@
package com.anytypeio.anytype.domain.auth.interactor
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.BaseUseCase
/**
* Use case for clearing last open object's id from user session.
* @see GetLastOpenedObject
* @see SaveLastOpenedObject
*/
class ClearLastOpenedObject(
private val repo: AuthRepository
) : BaseUseCase<Unit, BaseUseCase.None>() {
override suspend fun run(params: None) = safe { repo.clearLastOpenedObject() }
}

View file

@ -0,0 +1,66 @@
package com.anytypeio.anytype.domain.auth.interactor
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.block.repo.BlockRepository
/**
* Use case for fetching last open object's id for restoring user session.
* @see SaveLastOpenedObject
* @see ClearLastOpenedObject
*/
class GetLastOpenedObject(
private val authRepo: AuthRepository,
private val blockRepo: BlockRepository
) : BaseUseCase<GetLastOpenedObject.Response, BaseUseCase.None>() {
override suspend fun run(params: None) = safe {
val lastOpenObjectId = authRepo.getLastOpenedObjectId()
if (lastOpenObjectId == null) {
Response.Empty
} else {
val searchResults = blockRepo.searchObjects(
offset = 0,
limit = 1,
sorts = emptyList(),
filters = listOf(
Block.Content.DataView.Filter(
relationKey = Relations.ID,
condition = Block.Content.DataView.Filter.Condition.EQUAL,
operator = Block.Content.DataView.Filter.Operator.AND,
value = lastOpenObjectId
)
),
fulltext = ""
)
val wrappedObjects = searchResults.map { ObjectWrapper.Basic(it) }
val lastOpenedObject = wrappedObjects.firstOrNull { it.id == lastOpenObjectId }
if (lastOpenedObject != null) {
Response.Success(lastOpenedObject)
} else {
Response.NotFound(lastOpenObjectId)
}
}
}
sealed class Response {
/**
* There was no information about the last opened object.
*/
object Empty : Response()
/**
* The last opened object could not be found. It might habe been deleted.
*/
data class NotFound(val id: Id) : Response()
/**
* The last opened object has been found.
*/
data class Success(val obj: ObjectWrapper.Basic) : Response()
}
}

View file

@ -0,0 +1,16 @@
package com.anytypeio.anytype.domain.auth.interactor
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.BaseUseCase
/**
* Use case for saving last open object's id for restoring user session.
* @see GetLastOpenedObject
* @see ClearLastOpenedObject
*/
class SaveLastOpenedObject(
private val repo: AuthRepository
) : BaseUseCase<Unit, Id>() {
override suspend fun run(params: Id) = safe { repo.saveLastOpenedObjectId(params) }
}

View file

@ -3,6 +3,8 @@ package com.anytypeio.anytype.domain.auth.repo
import com.anytypeio.anytype.domain.auth.model.Account
import com.anytypeio.anytype.domain.auth.model.Wallet
import com.anytypeio.anytype.core_models.FlavourConfig
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import kotlinx.coroutines.flow.Flow
interface AuthRepository {
@ -49,4 +51,8 @@ interface AuthRepository {
suspend fun setCurrentAccount(id: String)
suspend fun getVersion(): String
suspend fun saveLastOpenedObjectId(id: Id)
suspend fun getLastOpenedObjectId() : Id?
suspend fun clearLastOpenedObject()
}

View file

@ -4,6 +4,7 @@ import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.base.Either
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
/**
* Use-case for opening a dashboard by sending a special request.
@ -11,7 +12,8 @@ import com.anytypeio.anytype.core_models.Payload
* @property repo
*/
class OpenDashboard(
private val repo: BlockRepository
private val repo: BlockRepository,
private val auth: AuthRepository,
) : BaseUseCase<Payload, OpenDashboard.Param?>() {
override suspend fun run(params: Param?) = try {
@ -20,7 +22,9 @@ class OpenDashboard(
contextId = params.contextId,
id = params.id
).let {
Either.Right(it)
Either.Right(it).also {
auth.clearLastOpenedObject()
}
}
else {
repo.getConfig().let { config ->
@ -28,7 +32,9 @@ class OpenDashboard(
contextId = config.home,
id = config.home
).let {
Either.Right(it)
Either.Right(it).also {
auth.clearLastOpenedObject()
}
}
}
}

View file

@ -4,12 +4,18 @@ import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.base.Result
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
open class OpenPage(
private val repo: BlockRepository
private val repo: BlockRepository,
private val auth: AuthRepository
) : BaseUseCase<Result<Payload>, OpenPage.Params>() {
override suspend fun run(params: Params) = safe { repo.openPage(params.id) }
override suspend fun run(params: Params) = safe {
repo.openPage(params.id).also {
auth.saveLastOpenedObjectId(params.id)
}
}
/**
* @property id page's id

View file

@ -2,9 +2,17 @@ package com.anytypeio.anytype.domain.sets
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.block.repo.BlockRepository
class OpenObjectSet(private val repo: BlockRepository) : BaseUseCase<Payload, Id>() {
override suspend fun run(params: Id) = safe { repo.openObjectSet(params) }
class OpenObjectSet(
private val repo: BlockRepository,
private val auth: AuthRepository
) : BaseUseCase<Payload, Id>() {
override suspend fun run(params: Id) = safe {
repo.openObjectSet(params).also {
auth.saveLastOpenedObjectId(params)
}
}
}

View file

@ -4,6 +4,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.core_models.CoroutineTestRule
import com.anytypeio.anytype.domain.common.MockDataFactory
import com.anytypeio.anytype.core_models.Config
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.dashboard.interactor.OpenDashboard
import com.nhaarman.mockitokotlin2.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -23,12 +24,15 @@ class OpenDashboardTest {
@Mock
lateinit var repo: BlockRepository
@Mock
lateinit var auth: AuthRepository
private lateinit var usecase: OpenDashboard
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
usecase = OpenDashboard(repo = repo)
usecase = OpenDashboard(repo = repo, auth = auth)
}
@Test

View file

@ -74,6 +74,7 @@ class DefaultAuthCache(
encryptedPrefs
.edit()
.remove(MNEMONIC_KEY)
.remove(LAST_OPENED_OBJECT_KEY)
.remove(CURRENT_ACCOUNT_ID_KEY)
.apply()
}
@ -88,8 +89,21 @@ class DefaultAuthCache(
encryptedPrefs.edit().putString(CURRENT_ACCOUNT_ID_KEY, id).apply()
}
override suspend fun saveLastOpenedObject(id: String) {
encryptedPrefs.edit().putString(LAST_OPENED_OBJECT_KEY, id).apply()
}
override suspend fun getLastOpenedObject(): String? {
return encryptedPrefs.getString(LAST_OPENED_OBJECT_KEY, null)
}
override suspend fun clearLastOpenedObject() {
encryptedPrefs.edit().remove(LAST_OPENED_OBJECT_KEY).apply()
}
companion object {
const val MNEMONIC_KEY = "mnemonic"
const val LAST_OPENED_OBJECT_KEY = "last_opened_object"
const val CURRENT_ACCOUNT_ID_KEY = "current_account"
}
}

View file

@ -134,7 +134,7 @@ class EditorViewModel(
private val updateDetail: UpdateDetail,
private val getCompatibleObjectTypes: GetCompatibleObjectTypes,
private val objectTypesProvider: ObjectTypesProvider,
private val searchObjects: SearchObjects
private val searchObjects: SearchObjects,
) : ViewStateViewModel<ViewState>(),
SupportNavigation<EventWrapper<AppNavigation.Command>>,
SupportCommand<Command>,

View file

@ -24,6 +24,8 @@ interface AppNavigation {
fun openDocument(id: String, editorSettings: EditorSettings?)
fun launchDocument(id: String)
fun launchObjectFromSplash(id: Id)
fun launchObjectSetFromSplash(id: Id)
fun launchObjectSet(id: Id)
fun startDesktopFromSplash()
@ -65,6 +67,8 @@ interface AppNavigation {
data class OpenObject(val id: String, val editorSettings: EditorSettings? = null) : Command()
data class LaunchDocument(val id: String) : Command()
data class LaunchObjectFromSplash(val target: Id) : Command()
data class LaunchObjectSetFromSplash(val target: Id) : Command()
object OpenProfile : Command()
object OpenKeychainScreen : Command()

View file

@ -11,15 +11,18 @@ import com.anytypeio.anytype.analytics.base.sendEvent
import com.anytypeio.anytype.analytics.base.updateUserProperties
import com.anytypeio.anytype.analytics.props.Props
import com.anytypeio.anytype.analytics.props.UserProperty
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_utils.common.EventWrapper
import com.anytypeio.anytype.core_utils.ui.ViewState
import com.anytypeio.anytype.domain.auth.interactor.CheckAuthorizationStatus
import com.anytypeio.anytype.domain.auth.interactor.GetLastOpenedObject
import com.anytypeio.anytype.domain.auth.interactor.LaunchAccount
import com.anytypeio.anytype.domain.auth.interactor.LaunchWallet
import com.anytypeio.anytype.domain.auth.model.AuthStatus
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.block.interactor.sets.StoreObjectTypes
import com.anytypeio.anytype.presentation.navigation.AppNavigation
import com.anytypeio.anytype.presentation.objects.SupportedLayouts
import kotlinx.coroutines.launch
import timber.log.Timber
@ -33,7 +36,8 @@ class SplashViewModel(
private val checkAuthorizationStatus: CheckAuthorizationStatus,
private val launchWallet: LaunchWallet,
private val launchAccount: LaunchAccount,
private val storeObjectTypes: StoreObjectTypes
private val storeObjectTypes: StoreObjectTypes,
private val getLastOpenedObject: GetLastOpenedObject
) : ViewModel() {
val state = MutableLiveData<ViewState<Nothing>>()
@ -106,9 +110,41 @@ class SplashViewModel(
storeObjectTypes.invoke(Unit).process(
failure = {
Timber.e(it, "Error while store account object types")
navigateToDashboard()
handleNavigation()
},
success = { navigateToDashboard() }
success = { handleNavigation() }
)
}
}
private fun handleNavigation() {
viewModelScope.launch {
getLastOpenedObject(BaseUseCase.None).process(
failure = { navigateToDashboard() },
success = { response ->
when(response) {
is GetLastOpenedObject.Response.Success -> {
if (SupportedLayouts.layouts.contains(response.obj.layout)) {
if (response.obj.layout == ObjectType.Layout.SET) {
navigation.postValue(
EventWrapper(
AppNavigation.Command.LaunchObjectSetFromSplash(response.obj.id)
)
)
} else {
navigation.postValue(
EventWrapper(
AppNavigation.Command.LaunchObjectFromSplash(response.obj.id)
)
)
}
} else {
navigateToDashboard()
}
}
else -> navigateToDashboard()
}
}
)
}
}

View file

@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.domain.auth.interactor.CheckAuthorizationStatus
import com.anytypeio.anytype.domain.auth.interactor.GetLastOpenedObject
import com.anytypeio.anytype.domain.auth.interactor.LaunchAccount
import com.anytypeio.anytype.domain.auth.interactor.LaunchWallet
import com.anytypeio.anytype.domain.block.interactor.sets.StoreObjectTypes
@ -18,7 +19,8 @@ class SplashViewModelFactory(
private val launchAccount: LaunchAccount,
private val launchWallet: LaunchWallet,
private val analytics: Analytics,
private val storeObjectTypes: StoreObjectTypes
private val storeObjectTypes: StoreObjectTypes,
private val getLastOpenedObject: GetLastOpenedObject
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -28,6 +30,7 @@ class SplashViewModelFactory(
launchAccount = launchAccount,
launchWallet = launchWallet,
analytics = analytics,
storeObjectTypes = storeObjectTypes
storeObjectTypes = storeObjectTypes,
getLastOpenedObject = getLastOpenedObject
) as T
}

View file

@ -6,9 +6,11 @@ import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.ui.ViewState
import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider
import com.anytypeio.anytype.domain.auth.interactor.CheckAuthorizationStatus
import com.anytypeio.anytype.domain.auth.interactor.GetLastOpenedObject
import com.anytypeio.anytype.domain.auth.interactor.LaunchAccount
import com.anytypeio.anytype.domain.auth.interactor.LaunchWallet
import com.anytypeio.anytype.domain.auth.model.AuthStatus
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.Either
import com.anytypeio.anytype.domain.block.interactor.sets.StoreObjectTypes
import com.anytypeio.anytype.domain.block.repo.BlockRepository
@ -46,10 +48,14 @@ class SplashViewModelTest {
@Mock
lateinit var repo: BlockRepository
@Mock
lateinit var auth: AuthRepository
@Mock
lateinit var objectTypesProvider: ObjectTypesProvider
lateinit var storeObjectTypes: StoreObjectTypes
private lateinit var storeObjectTypes: StoreObjectTypes
private lateinit var getLastOpenedObject: GetLastOpenedObject
lateinit var vm: SplashViewModel
@ -61,12 +67,17 @@ class SplashViewModelTest {
repo = repo,
objectTypesProvider = objectTypesProvider
)
getLastOpenedObject = GetLastOpenedObject(
authRepo = auth,
blockRepo = repo
)
vm = SplashViewModel(
checkAuthorizationStatus = checkAuthorizationStatus,
launchAccount = launchAccount,
launchWallet = launchWallet,
analytics = analytics,
storeObjectTypes = storeObjectTypes
storeObjectTypes = storeObjectTypes,
getLastOpenedObject = getLastOpenedObject
)
}
@ -79,6 +90,7 @@ class SplashViewModelTest {
stubCheckAuthStatus(response)
stubLaunchWallet()
stubLaunchAccount()
stubGetLastOpenedObject()
runBlocking {
verify(checkAuthorizationStatus, times(0)).invoke(any(), any(), any())
@ -96,6 +108,7 @@ class SplashViewModelTest {
stubCheckAuthStatus(response)
stubLaunchWallet()
stubLaunchAccount()
stubGetLastOpenedObject()
vm.onResume()
@ -114,6 +127,7 @@ class SplashViewModelTest {
stubCheckAuthStatus(response)
stubLaunchWallet()
stubLaunchAccount()
stubGetLastOpenedObject()
vm.onResume()
@ -132,6 +146,7 @@ class SplashViewModelTest {
stubCheckAuthStatus(response)
stubLaunchWallet()
stubLaunchAccount()
stubGetLastOpenedObject()
vm.onResume()
@ -172,6 +187,7 @@ class SplashViewModelTest {
val response = Either.Right(status)
stubCheckAuthStatus(response)
stubGetLastOpenedObject()
vm.onResume()
@ -229,4 +245,12 @@ class SplashViewModelTest {
onBlocking { invoke(any()) } doReturn Either.Right("accountId")
}
}
private fun stubGetLastOpenedObject() {
auth.stub {
onBlocking {
getLastOpenedObjectId()
} doReturn null
}
}
}