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

DROID-1118 Widgets | Enhancement | Persist widget session (#3060)

This commit is contained in:
Evgenii Kozlov 2023-03-30 12:08:09 +02:00 committed by GitHub
parent 9ff2400d76
commit e05b3e3173
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 248 additions and 65 deletions

View file

@ -126,11 +126,13 @@ object MainEntryModule {
fun provideLogoutUseCase(
repo: AuthRepository,
provider: ConfigStorage,
user: UserSettingsRepository,
dispatchers: AppCoroutineDispatchers
): Logout = Logout(
repo,
provider,
dispatchers
repo = repo,
user = user,
config = provider,
dispatchers = dispatchers
)
@JvmStatic

View file

@ -10,6 +10,7 @@ import com.anytypeio.anytype.domain.auth.interactor.Logout
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.config.UserSettingsRepository
import com.anytypeio.anytype.domain.misc.AppActionManager
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
import com.anytypeio.anytype.ext.DefaultDateHelper
@ -58,11 +59,13 @@ object DeletedAccountModule {
fun provideLogoutUseCase(
repo: AuthRepository,
provider: ConfigStorage,
dispatchers: AppCoroutineDispatchers
dispatchers: AppCoroutineDispatchers,
user: UserSettingsRepository
): Logout = Logout(
repo,
provider,
dispatchers
repo = repo,
config = provider,
user = user,
dispatchers = dispatchers
)
@JvmStatic
@ -89,4 +92,5 @@ interface DeletedAccountDependencies : ComponentDependencies {
fun dispatchers(): AppCoroutineDispatchers
fun configStorage(): ConfigStorage
fun authRepository(): AuthRepository
fun userSettingsRepository(): UserSettingsRepository
}

View file

@ -27,9 +27,6 @@ import com.anytypeio.anytype.domain.page.CloseBlock
import com.anytypeio.anytype.domain.page.CreateObject
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
import com.anytypeio.anytype.domain.templates.GetTemplates
import com.anytypeio.anytype.domain.widgets.CreateWidget
import com.anytypeio.anytype.domain.widgets.DeleteWidget
import com.anytypeio.anytype.domain.widgets.UpdateWidget
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
import com.anytypeio.anytype.presentation.home.HomeScreenViewModel
import com.anytypeio.anytype.presentation.home.Unsubscriber
@ -93,35 +90,6 @@ object HomeScreenModule {
dispatchers = dispatchers
)
@JvmStatic
@Provides
@PerScreen
fun createWidget(
repo: BlockRepository
): CreateWidget = CreateWidget(
repo = repo,
)
@JvmStatic
@Provides
@PerScreen
fun deleteWidget(
repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
): DeleteWidget = DeleteWidget(
repo = repo,
dispatchers = dispatchers
)
@JvmStatic
@Provides
@PerScreen
fun updateWidget(
repo: BlockRepository,
): UpdateWidget = UpdateWidget(
repo = repo
)
@JvmStatic
@Provides
@PerScreen

View file

@ -9,6 +9,7 @@ import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.config.UserSettingsRepository
import com.anytypeio.anytype.domain.debugging.DebugSync
import com.anytypeio.anytype.domain.device.ClearFileCache
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
@ -87,11 +88,13 @@ object AccountAndDataModule {
fun provideLogoutUseCase(
repo: AuthRepository,
provider: ConfigStorage,
user: UserSettingsRepository,
dispatchers: AppCoroutineDispatchers
): Logout = Logout(
repo,
provider,
dispatchers
repo = repo,
config = provider,
user = user,
dispatchers = dispatchers
)
@JvmStatic

View file

@ -6,6 +6,7 @@ import com.anytypeio.anytype.domain.auth.interactor.Logout
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.config.UserSettingsRepository
import com.anytypeio.anytype.domain.misc.AppActionManager
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
import com.anytypeio.anytype.ui.settings.LogoutWarningFragment
@ -51,10 +52,12 @@ object LogoutWarningModule {
fun provideLogoutUseCase(
repo: AuthRepository,
provider: ConfigStorage,
user: UserSettingsRepository,
dispatchers: AppCoroutineDispatchers
): Logout = Logout(
repo,
provider,
dispatchers
repo = repo,
config = provider,
user = user,
dispatchers = dispatchers
)
}

View file

@ -0,0 +1,8 @@
package com.anytypeio.anytype.core_models
/**
* @property [collapsed] list of collapsed widgets
*/
data class WidgetSession(
val collapsed: List<Id>
)

View file

@ -1,7 +1,8 @@
package com.anytypeio.anytype.data.auth.repo
import com.anytypeio.anytype.core_models.Wallpaper
import com.anytypeio.anytype.core_models.ThemeMode
import com.anytypeio.anytype.core_models.Wallpaper
import com.anytypeio.anytype.core_models.WidgetSession
interface UserSettingsCache {
suspend fun setDefaultObjectType(type: String, name: String)
@ -10,4 +11,7 @@ interface UserSettingsCache {
suspend fun getWallpaper() : Wallpaper
suspend fun setThemeMode(mode: ThemeMode)
suspend fun getThemeMode(): ThemeMode
suspend fun getWidgetSession() : WidgetSession
suspend fun saveWidgetSession(session: WidgetSession)
suspend fun clear()
}

View file

@ -1,7 +1,8 @@
package com.anytypeio.anytype.data.auth.repo
import com.anytypeio.anytype.core_models.Wallpaper
import com.anytypeio.anytype.core_models.ThemeMode
import com.anytypeio.anytype.core_models.Wallpaper
import com.anytypeio.anytype.core_models.WidgetSession
import com.anytypeio.anytype.domain.config.UserSettingsRepository
class UserSettingsDataRepository(private val cache: UserSettingsCache) : UserSettingsRepository {
@ -22,4 +23,12 @@ class UserSettingsDataRepository(private val cache: UserSettingsCache) : UserSet
}
override suspend fun getThemeMode(): ThemeMode = cache.getThemeMode()
override suspend fun getWidgetSession(): WidgetSession = cache.getWidgetSession()
override suspend fun saveWidgetSession(session: WidgetSession) = cache.saveWidgetSession(
session = session
)
override suspend fun clear() = cache.clear()
}

View file

@ -4,20 +4,22 @@ import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.Interactor
import com.anytypeio.anytype.domain.config.ConfigStorage
import kotlinx.coroutines.Dispatchers
import com.anytypeio.anytype.domain.config.UserSettingsRepository
/**
* Use case for logging out.
*/
class Logout(
private val repo: AuthRepository,
private val provider: ConfigStorage,
private val config: ConfigStorage,
private val user: UserSettingsRepository,
dispatchers: AppCoroutineDispatchers,
) : Interactor<Logout.Params>(context = dispatchers.io) {
override suspend fun run(params: Params) {
repo.logout(params.clearLocalRepositoryData)
provider.clear()
user.clear()
config.clear()
}
class Params(

View file

@ -2,6 +2,7 @@ package com.anytypeio.anytype.domain.config
import com.anytypeio.anytype.core_models.ThemeMode
import com.anytypeio.anytype.core_models.Wallpaper
import com.anytypeio.anytype.core_models.WidgetSession
interface UserSettingsRepository {
suspend fun setWallpaper(wallpaper: Wallpaper)
@ -10,4 +11,7 @@ interface UserSettingsRepository {
suspend fun getDefaultObjectType(): Pair<String?, String?>
suspend fun setThemeMode(mode: ThemeMode)
suspend fun getThemeMode(): ThemeMode
suspend fun getWidgetSession() : WidgetSession
suspend fun saveWidgetSession(session: WidgetSession)
suspend fun clear()
}

View file

@ -6,8 +6,9 @@ import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.ResultInteractor
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import javax.inject.Inject
class DeleteWidget(
class DeleteWidget @Inject constructor(
private val repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<DeleteWidget.Params, Payload>(dispatchers.io) {

View file

@ -0,0 +1,25 @@
package com.anytypeio.anytype.domain.widgets
import com.anytypeio.anytype.core_models.WidgetSession
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 GetWidgetSession @Inject constructor(
private val repo: UserSettingsRepository,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<Unit, WidgetSession>(dispatchers.io) {
override suspend fun doWork(params: Unit): WidgetSession = repo.getWidgetSession()
}
class SaveWidgetSession @Inject constructor(
private val repo: UserSettingsRepository,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<SaveWidgetSession.Params, Unit>(dispatchers.io) {
override suspend fun doWork(params: Params) {
repo.saveWidgetSession(params.session)
}
data class Params(val session: WidgetSession)
}

View file

@ -5,11 +5,12 @@ import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.domain.base.ResultatInteractor
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import javax.inject.Inject
/**
* Use-case for updating widget block contained in widgets.
*/
class UpdateWidget(
class UpdateWidget @Inject constructor(
private val repo: BlockRepository
) : ResultatInteractor<UpdateWidget.Params, Payload>() {

View file

@ -3,6 +3,7 @@ package com.anytypeio.anytype.persistence.repo
import android.content.SharedPreferences
import com.anytypeio.anytype.core_models.ThemeMode
import com.anytypeio.anytype.core_models.Wallpaper
import com.anytypeio.anytype.core_models.WidgetSession
import com.anytypeio.anytype.data.auth.repo.UserSettingsCache
class DefaultUserSettingsCache(private val prefs: SharedPreferences) : UserSettingsCache {
@ -121,6 +122,34 @@ class DefaultUserSettingsCache(private val prefs: SharedPreferences) : UserSetti
}
}
override suspend fun getWidgetSession(): WidgetSession {
return if (prefs.contains(COLLAPSED_WIDGETS_KEY)) {
WidgetSession(
collapsed = prefs.getStringSet(COLLAPSED_WIDGETS_KEY, emptySet())
.orEmpty()
.toList()
)
} else
WidgetSession(
collapsed = emptyList()
)
}
override suspend fun saveWidgetSession(session: WidgetSession) {
prefs
.edit()
.putStringSet(COLLAPSED_WIDGETS_KEY, session.collapsed.toSet())
.apply()
}
override suspend fun clear() {
prefs.edit()
.remove(DEFAULT_OBJECT_TYPE_ID_KEY)
.remove(DEFAULT_OBJECT_TYPE_NAME_KEY)
.remove(COLLAPSED_WIDGETS_KEY)
.apply()
}
companion object {
const val DEFAULT_OBJECT_TYPE_ID_KEY = "prefs.user_settings.default_object_type.id"
const val DEFAULT_OBJECT_TYPE_NAME_KEY = "prefs.user_settings.default_object_type.name"
@ -136,5 +165,7 @@ class DefaultUserSettingsCache(private val prefs: SharedPreferences) : UserSetti
const val THEME_TYPE_SYSTEM = 1
const val THEME_TYPE_LIGHT = 2
const val THEME_TYPE_NIGHT = 3
const val COLLAPSED_WIDGETS_KEY = "prefs.user_settings.collapsed-widgets"
}
}

View file

@ -16,6 +16,7 @@ import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Position
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.WidgetLayout
import com.anytypeio.anytype.core_models.WidgetSession
import com.anytypeio.anytype.core_models.ext.process
import com.anytypeio.anytype.core_utils.ext.letNotNull
import com.anytypeio.anytype.core_utils.ext.replace
@ -38,6 +39,8 @@ import com.anytypeio.anytype.domain.page.CloseBlock
import com.anytypeio.anytype.domain.page.CreateObject
import com.anytypeio.anytype.domain.widgets.CreateWidget
import com.anytypeio.anytype.domain.widgets.DeleteWidget
import com.anytypeio.anytype.domain.widgets.GetWidgetSession
import com.anytypeio.anytype.domain.widgets.SaveWidgetSession
import com.anytypeio.anytype.domain.widgets.UpdateWidget
import com.anytypeio.anytype.presentation.extension.sendAnalyticsObjectCreateEvent
import com.anytypeio.anytype.presentation.home.Command.ChangeWidgetType.Companion.UNDEFINED_LAYOUT_CODE
@ -74,6 +77,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
class HomeScreenViewModel(
@ -99,7 +103,9 @@ class HomeScreenViewModel(
private val unsubscriber: Unsubscriber,
private val getDefaultPageType: GetDefaultPageType,
private val appActionManager: AppActionManager,
private val analytics: Analytics
private val analytics: Analytics,
private val getWidgetSession: GetWidgetSession,
private val saveWidgetSession: SaveWidgetSession
) : NavigationViewModel<HomeScreenViewModel.Navigation>(),
Reducer<ObjectView, Payload>,
WidgetActiveViewStateHolder by widgetActiveViewStateHolder,
@ -111,6 +117,8 @@ class HomeScreenViewModel(
val commands = MutableSharedFlow<Command>()
val mode = MutableStateFlow<InteractionMode>(InteractionMode.Default)
private var isWidgetSessionRestored = false
private val isEmptyingBinInProgress = MutableStateFlow(false)
private val objectViewState = MutableStateFlow<ObjectViewState>(ObjectViewState.Idle)
@ -300,6 +308,11 @@ class HomeScreenViewModel(
private fun proceedWithClosingWidgetObject(widgetObject: Id) {
viewModelScope.launch {
saveWidgetSession.execute(
SaveWidgetSession.Params(
WidgetSession(collapsed = collapsedWidgetStateHolder.get())
)
)
val subscriptions = widgets.value.map { widget ->
if (widget.source is Widget.Source.Bundled)
widget.source.id
@ -697,6 +710,7 @@ class HomeScreenViewModel(
}
if (deletedWidgets.isNotEmpty()) {
viewModelScope.launch {
collapsedWidgetStateHolder.onWidgetDeleted(deletedWidgets)
unsubscriber.unsubscribe(deletedWidgets)
}
}
@ -704,7 +718,19 @@ class HomeScreenViewModel(
fun onStart() {
Timber.d("onStart")
proceedWithOpeningWidgetObject(widgetObject = configStorage.get().widgets)
if (!isWidgetSessionRestored) {
viewModelScope.launch {
val session = withContext(appCoroutineDispatchers.io) {
getWidgetSession.execute(Unit).getOrNull()
}
if (session != null && session.collapsed.isNotEmpty()) {
collapsedWidgetStateHolder.set(session.collapsed)
}
proceedWithOpeningWidgetObject(widgetObject = configStorage.get().widgets)
}
} else {
proceedWithOpeningWidgetObject(widgetObject = configStorage.get().widgets)
}
}
fun onStop() {
@ -836,7 +862,9 @@ class HomeScreenViewModel(
private val unsubscriber: Unsubscriber,
private val getDefaultPageType: GetDefaultPageType,
private val appActionManager: AppActionManager,
private val analytics: Analytics
private val analytics: Analytics,
private val getWidgetSession: GetWidgetSession,
private val saveWidgetSession: SaveWidgetSession
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T = HomeScreenViewModel(
@ -862,7 +890,9 @@ class HomeScreenViewModel(
unsubscriber = unsubscriber,
getDefaultPageType = getDefaultPageType,
appActionManager = appActionManager,
analytics = analytics
analytics = analytics,
getWidgetSession = getWidgetSession,
saveWidgetSession = saveWidgetSession
) as T
}

View file

@ -10,6 +10,9 @@ interface CollapsedWidgetStateHolder {
fun onToggleCollapsedWidgetState(widget: Id)
fun isCollapsed(widget: Id): Flow<Boolean>
fun set(collapsed: List<Id>)
fun get() : List<Id>
fun onWidgetDeleted(widgets: List<Id>)
class Impl @Inject constructor(): CollapsedWidgetStateHolder {
private val collapsedWidgets = MutableStateFlow<List<Id>>(emptyList())
@ -29,5 +32,18 @@ interface CollapsedWidgetStateHolder {
override fun isCollapsed(widget: Id) = collapsedWidgets.map { collapsed ->
collapsed.contains(widget)
}
override fun set(collapsed: List<Id>) {
collapsedWidgets.value = collapsed
}
override fun get(): List<Id> = collapsedWidgets.value
override fun onWidgetDeleted(widgets: List<Id>) {
val curr = collapsedWidgets.value
if (curr.isNotEmpty()) {
collapsedWidgets.value = curr - widgets
}
}
}
}

View file

@ -8,10 +8,13 @@ import com.anytypeio.anytype.domain.auth.interactor.Logout
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.config.UserSettingsRepository
import com.anytypeio.anytype.domain.misc.AppActionManager
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
import com.anytypeio.anytype.presentation.auth.account.DeletedAccountViewModel
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import java.time.Duration
import kotlin.test.assertEquals
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.Before
import org.junit.Rule
@ -21,8 +24,6 @@ import org.mockito.MockitoAnnotations
import org.mockito.kotlin.times
import org.mockito.kotlin.verifyBlocking
import org.mockito.kotlin.verifyNoInteractions
import java.time.Duration
import kotlin.test.assertEquals
@ExperimentalCoroutinesApi
class DeleteAccountViewModelTest {
@ -42,6 +43,9 @@ class DeleteAccountViewModelTest {
@Mock
lateinit var repo: AuthRepository
@Mock
lateinit var userSettingsRepository: UserSettingsRepository
@Mock
lateinit var helper: DateHelper
@ -71,8 +75,9 @@ class DeleteAccountViewModelTest {
)
logout = Logout(
repo = repo,
provider = configStorage,
dispatchers = testDispatchers
config = configStorage,
dispatchers = testDispatchers,
user = userSettingsRepository
)
vm = DeletedAccountViewModel(
restoreAccount = restoreAccount,

View file

@ -10,6 +10,7 @@ import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectView
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.SmartBlockType
import com.anytypeio.anytype.core_models.StubConfig
import com.anytypeio.anytype.core_models.StubLinkToObjectBlock
@ -17,6 +18,7 @@ import com.anytypeio.anytype.core_models.StubObject
import com.anytypeio.anytype.core_models.StubObjectView
import com.anytypeio.anytype.core_models.StubSmartBlock
import com.anytypeio.anytype.core_models.StubWidgetBlock
import com.anytypeio.anytype.core_models.WidgetSession
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.Resultat
import com.anytypeio.anytype.domain.bin.EmptyBin
@ -36,6 +38,8 @@ import com.anytypeio.anytype.domain.page.CloseBlock
import com.anytypeio.anytype.domain.page.CreateObject
import com.anytypeio.anytype.domain.widgets.CreateWidget
import com.anytypeio.anytype.domain.widgets.DeleteWidget
import com.anytypeio.anytype.domain.widgets.GetWidgetSession
import com.anytypeio.anytype.domain.widgets.SaveWidgetSession
import com.anytypeio.anytype.domain.widgets.UpdateWidget
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.search.Subscriptions
@ -136,6 +140,12 @@ class HomeScreenViewModelTest {
@Mock
lateinit var analytics: Analytics
@Mock
lateinit var saveWidgetSession: SaveWidgetSession
@Mock
lateinit var getWidgetSession: GetWidgetSession
private val objectPayloadDispatcher = Dispatcher.Default<Payload>()
private val widgetEventDispatcher = Dispatcher.Default<WidgetDispatchEvent>()
@ -184,6 +194,7 @@ class HomeScreenViewModelTest {
stubInterceptEvents(events)
stubOpenObject(givenObjectView)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
val vm = buildViewModel()
@ -204,6 +215,26 @@ class HomeScreenViewModelTest {
verify(openObject, times(1)).stream(OpenObject.Params(WIDGET_OBJECT_ID, false))
}
private fun stubGetWidgetSession(
session: WidgetSession = WidgetSession(emptyList())
) {
getWidgetSession.stub {
onBlocking {
execute(any())
} doReturn Resultat.Success(session)
}
}
private fun stubSaveWidgetSession(
session: WidgetSession = WidgetSession(emptyList())
) {
saveWidgetSession.stub {
onBlocking {
execute(SaveWidgetSession.Params(session))
} doReturn Resultat.Success(Unit)
}
}
@Test
fun `should emit only bin and actions when home screen has no associated widgets except the default ones`() =
runTest {
@ -229,6 +260,7 @@ class HomeScreenViewModelTest {
stubInterceptEvents(events = emptyFlow())
stubOpenObject(givenObjectView)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
val vm = buildViewModel()
@ -306,6 +338,7 @@ class HomeScreenViewModelTest {
)
stubCollapsedWidgetState(any())
stubWidgetActiveView(widgetBlock)
stubGetWidgetSession()
val vm = buildViewModel()
@ -412,6 +445,7 @@ class HomeScreenViewModelTest {
stubCollapsedWidgetState(any())
stubWidgetActiveView(widgetBlock)
stubGetWidgetSession()
val vm = buildViewModel()
@ -590,6 +624,7 @@ class HomeScreenViewModelTest {
)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
stubWidgetActiveView(favoriteWidgetBlock)
val vm = buildViewModel()
@ -744,7 +779,7 @@ class HomeScreenViewModelTest {
targets = emptyList()
)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
val vm = buildViewModel()
@ -836,6 +871,30 @@ class HomeScreenViewModelTest {
targets = emptyList()
)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
stubSaveWidgetSession()
getDefaultPageType.stub {
onBlocking {
execute(any())
} doReturn Resultat.Success(
GetDefaultPageType.Response(
null, null
)
)
}
storelessSubscriptionContainer.stub {
onBlocking {
subscribe(
StoreSearchByIdsParams(
subscription = HomeScreenViewModel.HOME_SCREEN_SPACE_OBJECT_SUBSCRIPTION,
targets = listOf(config.workspace),
keys = listOf(Relations.ID, Relations.ICON_EMOJI, Relations.ICON_IMAGE)
)
)
} doReturn emptyFlow()
}
val givenPayload = Payload(
context = WIDGET_OBJECT_ID,
@ -869,6 +928,8 @@ class HomeScreenViewModelTest {
vm.onStart()
advanceUntilIdle()
vm.onDropDownMenuAction(
widget = widgetBlock.id,
DropDownMenuAction.RemoveWidget
@ -951,6 +1012,7 @@ class HomeScreenViewModelTest {
targets = emptyList()
)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
val vm = buildViewModel()
@ -1019,6 +1081,7 @@ class HomeScreenViewModelTest {
targets = emptyList()
)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
stubCloseObject()
val vm = buildViewModel()
@ -1148,6 +1211,7 @@ class HomeScreenViewModelTest {
)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
stubWidgetActiveView(favoriteWidgetBlock)
val vm = buildViewModel()
@ -1282,8 +1346,8 @@ class HomeScreenViewModelTest {
)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
stubWidgetActiveView(favoriteWidgetBlock)
stubCloseObject()
val vm = buildViewModel()
@ -1486,6 +1550,7 @@ class HomeScreenViewModelTest {
)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
stubWidgetActiveView(favoriteWidgetBlock)
stubCloseObject()
@ -1699,7 +1764,7 @@ class HomeScreenViewModelTest {
targets = emptyList()
)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
val vm = buildViewModel()
@ -1768,7 +1833,7 @@ class HomeScreenViewModelTest {
targets = emptyList()
)
stubCollapsedWidgetState(any())
stubGetWidgetSession()
val vm = buildViewModel()
@ -1888,7 +1953,9 @@ class HomeScreenViewModelTest {
unsubscriber = unsubscriber,
getDefaultPageType = getDefaultPageType,
appActionManager = appActionManager,
analytics = analytics
analytics = analytics,
getWidgetSession = getWidgetSession,
saveWidgetSession = saveWidgetSession
)
companion object {