mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2731 Vault | Enhancement | Restoring either last opened space or vault (#1528)
This commit is contained in:
parent
fda05fa782
commit
22d78b0727
15 changed files with 110 additions and 30 deletions
|
@ -18,7 +18,6 @@ import androidx.lifecycle.lifecycleScope
|
|||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.anytypeio.anytype.BuildConfig
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_ui.extensions.throttledClick
|
||||
|
@ -103,15 +102,7 @@ class HomeScreenFragment : BaseComposeFragment() {
|
|||
onClick = { vm.onCreateNewObjectLongClicked() }
|
||||
),
|
||||
onProfileClicked = throttledClick(
|
||||
onClick = {
|
||||
runCatching {
|
||||
if (BuildConfig.DEBUG) {
|
||||
findNavController().navigate(R.id.action_open_vault)
|
||||
} else {
|
||||
findNavController().navigate(R.id.action_open_spaces)
|
||||
}
|
||||
}
|
||||
}
|
||||
onClick = vm::onVaultClicked
|
||||
),
|
||||
onSpaceWidgetClicked = throttledClick(
|
||||
onClick = vm::onSpaceSettingsClicked
|
||||
|
@ -329,6 +320,13 @@ class HomeScreenFragment : BaseComposeFragment() {
|
|||
Timber.e(it, "Error while opening global search screen")
|
||||
}
|
||||
}
|
||||
is Command.OpenVault -> {
|
||||
runCatching {
|
||||
findNavController().navigate(R.id.action_open_vault)
|
||||
}.onFailure {
|
||||
Timber.e(it, "Error while opening vault from home screen")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ class SplashFragment : BaseFragment<FragmentSplashBinding>(R.layout.fragment_spl
|
|||
is SplashViewModel.Command.NavigateToDashboard -> {
|
||||
try {
|
||||
findNavController().navigate(
|
||||
R.id.action_splashScreen_to_vaultScreen,
|
||||
R.id.action_splashScreen_to_homeScreen,
|
||||
args = HomeScreenFragment.args(command.deeplink)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
|
@ -92,14 +92,15 @@ class SplashFragment : BaseFragment<FragmentSplashBinding>(R.layout.fragment_spl
|
|||
toast("Error while navigating to desktop: ${e.message}")
|
||||
}
|
||||
}
|
||||
is SplashViewModel.Command.NavigateToWidgets -> {
|
||||
is SplashViewModel.Command.NavigateToVault -> {
|
||||
try {
|
||||
findNavController().navigate(
|
||||
R.id.action_splashScreen_to_widgets
|
||||
R.id.action_splashScreen_to_vaultScreen,
|
||||
args = HomeScreenFragment.args(command.deeplink)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error while opening widgets from splash screen")
|
||||
toast("Error while navigating to widgets: ${e.message}")
|
||||
Timber.e(e, "Error while opening dashboard from splash screen")
|
||||
toast("Error while navigating to desktop: ${e.message}")
|
||||
}
|
||||
}
|
||||
is SplashViewModel.Command.NavigateToObject -> {
|
||||
|
|
|
@ -202,8 +202,7 @@
|
|||
android:name="com.anytypeio.anytype.ui.vault.VaultFragment">
|
||||
<action
|
||||
android:id="@+id/openSpace"
|
||||
app:destination="@id/homeScreen"
|
||||
app:enterAnim="@anim/slide_in_right" />
|
||||
app:destination="@id/homeScreen" />
|
||||
</fragment>
|
||||
|
||||
<dialog
|
||||
|
|
|
@ -11,6 +11,7 @@ import kotlinx.coroutines.flow.Flow
|
|||
interface UserSettingsCache {
|
||||
suspend fun setCurrentSpace(space: SpaceId)
|
||||
suspend fun getCurrentSpace(): SpaceId?
|
||||
suspend fun clearCurrentSpace()
|
||||
|
||||
suspend fun setDefaultObjectType(space: SpaceId, type: TypeId)
|
||||
suspend fun getDefaultObjectType(space: SpaceId): TypeId?
|
||||
|
|
|
@ -62,6 +62,8 @@ class UserSettingsDataRepository(private val cache: UserSettingsCache) : UserSet
|
|||
|
||||
override suspend fun getCurrentSpace(): SpaceId? = cache.getCurrentSpace()
|
||||
|
||||
override suspend fun clearCurrentSpace() = cache.clearCurrentSpace()
|
||||
|
||||
override suspend fun setLastOpenedObject(id: Id, space: SpaceId) {
|
||||
cache.setLastOpenedObject(id, space)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.anytypeio.anytype.domain.auth.interactor
|
||||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.DVFilter
|
||||
import com.anytypeio.anytype.core_models.DVFilterCondition
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
|
@ -50,7 +49,7 @@ class GetLastOpenedObject(
|
|||
/**
|
||||
* There was no information about the last opened object.
|
||||
*/
|
||||
object Empty : Response()
|
||||
data object Empty : Response()
|
||||
|
||||
/**
|
||||
* The last opened object could not be found. It might have been deleted.
|
||||
|
|
|
@ -12,6 +12,7 @@ interface UserSettingsRepository {
|
|||
|
||||
suspend fun setCurrentSpace(space: SpaceId)
|
||||
suspend fun getCurrentSpace(): SpaceId?
|
||||
suspend fun clearCurrentSpace()
|
||||
|
||||
suspend fun setWallpaper(space: Id, wallpaper: Wallpaper)
|
||||
suspend fun getWallpaper(space: Id): Wallpaper
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package com.anytypeio.anytype.domain.spaces
|
||||
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.ResultInteractor
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class ClearLastOpenedSpace @Inject constructor(
|
||||
private val repo: UserSettingsRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): ResultInteractor<Unit, Unit>(dispatchers.io) {
|
||||
|
||||
override suspend fun doWork(params: Unit) {
|
||||
return repo.clearCurrentSpace()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.anytypeio.anytype.domain.spaces
|
||||
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.ResultInteractor
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class GetLastOpenedSpace @Inject constructor(
|
||||
private val repo: UserSettingsRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): ResultInteractor<Unit, SpaceId?>(dispatchers.io) {
|
||||
|
||||
override suspend fun doWork(params: Unit): SpaceId? {
|
||||
return repo.getCurrentSpace()
|
||||
}
|
||||
}
|
|
@ -51,6 +51,12 @@ class DefaultUserSettingsCache(
|
|||
SpaceId(value)
|
||||
}
|
||||
|
||||
override suspend fun clearCurrentSpace() {
|
||||
prefs.edit()
|
||||
.putString(CURRENT_SPACE_KEY, "")
|
||||
.apply()
|
||||
}
|
||||
|
||||
override suspend fun setDefaultObjectType(space: SpaceId, type: TypeId) {
|
||||
val curr = prefs
|
||||
.getString(DEFAULT_OBJECT_TYPES_KEY, NO_VALUE)
|
||||
|
|
|
@ -60,6 +60,7 @@ import com.anytypeio.anytype.domain.page.CloseBlock
|
|||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.search.GetLastSearchQuery
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.spaces.ClearLastOpenedSpace
|
||||
import com.anytypeio.anytype.domain.spaces.GetSpaceView
|
||||
import com.anytypeio.anytype.domain.types.GetPinnedObjectTypes
|
||||
import com.anytypeio.anytype.domain.widgets.CreateWidget
|
||||
|
@ -196,7 +197,8 @@ class HomeScreenViewModel(
|
|||
private val createBlock: CreateBlock,
|
||||
private val dateProvider: DateProvider,
|
||||
private val addObjectToCollection: AddObjectToCollection,
|
||||
private val getLastSearchQuery: GetLastSearchQuery
|
||||
private val getLastSearchQuery: GetLastSearchQuery,
|
||||
private val clearLastOpenedSpace: ClearLastOpenedSpace
|
||||
) : NavigationViewModel<HomeScreenViewModel.Navigation>(),
|
||||
Reducer<ObjectView, Payload>,
|
||||
WidgetActiveViewStateHolder by widgetActiveViewStateHolder,
|
||||
|
@ -1639,6 +1641,20 @@ class HomeScreenViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun onVaultClicked() {
|
||||
viewModelScope.launch {
|
||||
clearLastOpenedSpace.async(Unit).fold(
|
||||
onSuccess = {
|
||||
Timber.d("Cleared last opened space before opening vault")
|
||||
},
|
||||
onFailure = {
|
||||
Timber.e(it, "Error while clearing last opened space before opening vault")
|
||||
}
|
||||
)
|
||||
commands.emit(Command.OpenVault)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
Timber.d("onCleared")
|
||||
|
@ -2072,7 +2088,8 @@ class HomeScreenViewModel(
|
|||
private val dateProvider: DateProvider,
|
||||
private val coverImageHashProvider: CoverImageHashProvider,
|
||||
private val addObjectToCollection: AddObjectToCollection,
|
||||
private val getLastSearchQuery: GetLastSearchQuery
|
||||
private val getLastSearchQuery: GetLastSearchQuery,
|
||||
private val clearLastOpenedSpace: ClearLastOpenedSpace
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T = HomeScreenViewModel(
|
||||
|
@ -2120,7 +2137,8 @@ class HomeScreenViewModel(
|
|||
createBlock = createBlock,
|
||||
dateProvider = dateProvider,
|
||||
addObjectToCollection = addObjectToCollection,
|
||||
getLastSearchQuery = getLastSearchQuery
|
||||
getLastSearchQuery = getLastSearchQuery,
|
||||
clearLastOpenedSpace = clearLastOpenedSpace
|
||||
) as T
|
||||
}
|
||||
|
||||
|
@ -2165,6 +2183,8 @@ sealed class Command {
|
|||
|
||||
data class OpenGlobalSearchScreen(val initialQuery: String, val space: Id) : Command()
|
||||
|
||||
data object OpenVault: Command()
|
||||
|
||||
data class SelectWidgetType(
|
||||
val ctx: Id,
|
||||
val source: Id,
|
||||
|
|
|
@ -29,6 +29,7 @@ import com.anytypeio.anytype.domain.base.BaseUseCase
|
|||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.misc.LocaleProvider
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.spaces.GetLastOpenedSpace
|
||||
import com.anytypeio.anytype.domain.subscriptions.GlobalSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.BuildConfig
|
||||
|
@ -56,7 +57,8 @@ class SplashViewModel(
|
|||
private val localeProvider: LocaleProvider,
|
||||
private val spaceManager: SpaceManager,
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
private val globalSubscriptionManager: GlobalSubscriptionManager
|
||||
private val globalSubscriptionManager: GlobalSubscriptionManager,
|
||||
private val getLastOpenedSpace: GetLastOpenedSpace
|
||||
) : ViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
|
||||
|
||||
val state = MutableStateFlow<ViewState<Any>>(ViewState.Init)
|
||||
|
@ -246,7 +248,12 @@ class SplashViewModel(
|
|||
}
|
||||
|
||||
private suspend fun proceedWithDashboardNavigation(deeplink: String? = null) {
|
||||
commands.emit(Command.NavigateToDashboard(deeplink))
|
||||
val space = getLastOpenedSpace.async(Unit).getOrNull()
|
||||
if (space != null) {
|
||||
commands.emit(Command.NavigateToDashboard(deeplink))
|
||||
} else {
|
||||
commands.emit(Command.NavigateToVault(deeplink))
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateUserProps(id: String) {
|
||||
|
@ -275,7 +282,7 @@ class SplashViewModel(
|
|||
|
||||
sealed class Command {
|
||||
data class NavigateToDashboard(val deeplink: String? = null) : Command()
|
||||
data object NavigateToWidgets : Command()
|
||||
data class NavigateToVault(val deeplink: String? = null) : Command()
|
||||
data object NavigateToAuthStart : Command()
|
||||
data object NavigateToMigration: Command()
|
||||
data object CheckAppStartIntent : Command()
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.anytypeio.anytype.domain.auth.interactor.LaunchAccount
|
|||
import com.anytypeio.anytype.domain.auth.interactor.LaunchWallet
|
||||
import com.anytypeio.anytype.domain.misc.LocaleProvider
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.spaces.GetLastOpenedSpace
|
||||
import com.anytypeio.anytype.domain.subscriptions.GlobalSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
||||
|
@ -31,7 +32,8 @@ class SplashViewModelFactory @Inject constructor(
|
|||
private val localeProvider: LocaleProvider,
|
||||
private val spaceManager: SpaceManager,
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
private val globalSubscriptionManager: GlobalSubscriptionManager
|
||||
private val globalSubscriptionManager: GlobalSubscriptionManager,
|
||||
private val getLastOpenedSpace: GetLastOpenedSpace
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -47,6 +49,7 @@ class SplashViewModelFactory @Inject constructor(
|
|||
localeProvider = localeProvider,
|
||||
spaceManager = spaceManager,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
globalSubscriptionManager = globalSubscriptionManager
|
||||
globalSubscriptionManager = globalSubscriptionManager,
|
||||
getLastOpenedSpace = getLastOpenedSpace
|
||||
) as T
|
||||
}
|
|
@ -58,6 +58,7 @@ import com.anytypeio.anytype.domain.page.CloseBlock
|
|||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.search.GetLastSearchQuery
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.spaces.ClearLastOpenedSpace
|
||||
import com.anytypeio.anytype.domain.spaces.GetSpaceView
|
||||
import com.anytypeio.anytype.domain.types.GetPinnedObjectTypes
|
||||
import com.anytypeio.anytype.domain.widgets.CreateWidget
|
||||
|
@ -247,6 +248,9 @@ class HomeScreenViewModelTest {
|
|||
@Mock
|
||||
lateinit var getLastSearchQuery: GetLastSearchQuery
|
||||
|
||||
@Mock
|
||||
lateinit var clearLastOpenedSpace: ClearLastOpenedSpace
|
||||
|
||||
lateinit var userPermissionProvider: UserPermissionProvider
|
||||
|
||||
private val objectPayloadDispatcher = Dispatcher.Default<Payload>()
|
||||
|
@ -2944,7 +2948,8 @@ class HomeScreenViewModelTest {
|
|||
createDataViewObject = createDataViewObject,
|
||||
dateProvider = dateProvider,
|
||||
addObjectToCollection = addObjectToCollection,
|
||||
getLastSearchQuery = getLastSearchQuery
|
||||
getLastSearchQuery = getLastSearchQuery,
|
||||
clearLastOpenedSpace = clearLastOpenedSpace
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -17,6 +17,7 @@ import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
|||
import com.anytypeio.anytype.domain.misc.LocaleProvider
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.spaces.GetLastOpenedSpace
|
||||
import com.anytypeio.anytype.domain.subscriptions.GlobalSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
||||
|
@ -87,9 +88,12 @@ class SplashViewModelTest {
|
|||
@Mock
|
||||
lateinit var analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
|
||||
@Mock
|
||||
lateinit var getLastOpenedSpace: GetLastOpenedSpace
|
||||
|
||||
lateinit var vm: SplashViewModel
|
||||
|
||||
val defaultSpaceConfig = StubConfig()
|
||||
private val defaultSpaceConfig = StubConfig()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
|
@ -114,7 +118,8 @@ class SplashViewModelTest {
|
|||
localeProvider = localeProvider,
|
||||
spaceManager = spaceManager,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
globalSubscriptionManager = globalSubscriptionManager
|
||||
globalSubscriptionManager = globalSubscriptionManager,
|
||||
getLastOpenedSpace = getLastOpenedSpace
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue