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

DROID-2463 Analytics | Enhancement | Space + permission analytics (#1172)

Co-authored-by: uburoiubu <ubuphobos@gmail.com>
This commit is contained in:
Konstantin Ivanov 2024-04-30 09:31:00 +02:00 committed by uburoiubu
parent 702ff14210
commit e6ffdf56d9
No known key found for this signature in database
GPG key ID: C8FB80E0A595FBB6
127 changed files with 1904 additions and 802 deletions

View file

@ -324,4 +324,6 @@ object EventsPropertiesKey {
const val view = "view"
const val step = "step"
const val name = "name"
const val spaceType = "spaceType"
const val permissions = "permissions"
}

View file

@ -95,6 +95,7 @@ import com.anytypeio.anytype.domain.workspace.FileLimitsEventChannel
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.editor.DocumentExternalEventReducer
import com.anytypeio.anytype.presentation.editor.Editor
@ -295,6 +296,9 @@ open class EditorTestSetup {
@Mock
lateinit var permissions: UserPermissionProvider
@Mock
lateinit var analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
lateinit var interceptFileLimitEvents: InterceptFileLimitEvents
lateinit var addRelationToObject: AddRelationToObject
@ -464,7 +468,9 @@ open class EditorTestSetup {
createTable = createTable,
fillTableRow = fillTableRow,
clearBlockContent = clearBlockContent,
clearBlockStyle = clearBlockStyle
clearBlockStyle = clearBlockStyle,
analyticsSpaceHelperDelegate = analyticSpaceHelperDelegate,
spaceManager = spaceManager
),
createObjectAsMentionOrLink = createObjectAsMentionOrLink,
interceptThreadStatus = interceptThreadStatus,
@ -501,7 +507,8 @@ open class EditorTestSetup {
ctx = root,
space = SpaceId(defaultSpace)
),
permissions = permissions
permissions = permissions,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
}

View file

@ -57,6 +57,7 @@ import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
import com.anytypeio.anytype.domain.unsplash.UnsplashRepository
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.emojifier.data.DefaultDocumentEmojiIconProvider
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
@ -178,6 +179,9 @@ abstract class TestObjectSetSetup {
@Mock
lateinit var getNetworkMode: GetNetworkMode
@Mock
lateinit var analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
private lateinit var getTemplates: GetTemplates
private lateinit var getDefaultObjectType: GetDefaultObjectType
@ -306,7 +310,8 @@ abstract class TestObjectSetSetup {
ctx = ctx,
space = SpaceId(defaultSpace)
),
permissions = permissions
permissions = permissions,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
}

View file

@ -5,6 +5,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.relations.add.AddObjectRelationViewModel
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider
@ -39,14 +40,16 @@ object AddDataViewRelationObjectValueModule {
storeOfObjectTypes: StoreOfObjectTypes,
searchObjects: SearchObjects,
urlBuilder: UrlBuilder,
spaceManager: SpaceManager
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): AddObjectRelationViewModel.Factory = AddObjectRelationViewModel.Factory(
relations = relations,
values = values,
searchObjects = searchObjects,
urlBuilder = urlBuilder,
storeOfObjectTypes = storeOfObjectTypes,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
}

View file

@ -5,6 +5,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.relations.add.AddObjectRelationViewModel
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider
@ -39,13 +40,15 @@ object AddObjectRelationModule {
storeOfObjectTypes: StoreOfObjectTypes,
searchObjects: SearchObjects,
urlBuilder: UrlBuilder,
spaceManager: SpaceManager
spaceManager: SpaceManager,
spaceHelperDelegate: AnalyticSpaceHelperDelegate
): AddObjectRelationViewModel.Factory = AddObjectRelationViewModel.Factory(
relations = relations,
values = values,
searchObjects = searchObjects,
urlBuilder = urlBuilder,
storeOfObjectTypes = storeOfObjectTypes,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = spaceHelperDelegate
)
}

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.networkmode.GetNetworkMode
import com.anytypeio.anytype.domain.networkmode.SetNetworkMode
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.settings.PreferencesViewModel
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
import com.anytypeio.anytype.presentation.util.NetworkModeCopyFileToCacheDirectory
@ -64,4 +65,5 @@ interface AppPreferencesDependencies : ComponentDependencies {
fun dispatchers(): AppCoroutineDispatchers
fun authRepository(): AuthRepository
fun analytics(): Analytics
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -13,6 +13,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.linking.BackLinkOrAddToObjectViewModelFactory
import com.anytypeio.anytype.ui.linking.BacklinkOrAddToObjectFragment
import dagger.Binds
@ -79,4 +80,5 @@ interface BacklinkOrAddToObjectDependencies : ComponentDependencies {
fun dispatchers(): AppCoroutineDispatchers
fun analytics(): Analytics
fun spaceManager(): SpaceManager
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -100,6 +100,7 @@ import com.anytypeio.anytype.domain.unsplash.UnsplashRepository
import com.anytypeio.anytype.domain.workspace.FileLimitsEventChannel
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.editor.DocumentExternalEventReducer
@ -288,7 +289,8 @@ object EditorSessionModule {
templatesContainer: ObjectTypeTemplatesContainer,
storelessSubscriptionContainer: StorelessSubscriptionContainer,
dispatchers: AppCoroutineDispatchers,
getNetworkMode: GetNetworkMode
getNetworkMode: GetNetworkMode,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): EditorViewModelFactory = EditorViewModelFactory(
params = params,
permissions = permissions,
@ -332,7 +334,8 @@ object EditorSessionModule {
templatesContainer = templatesContainer,
dispatchers = dispatchers,
storelessSubscriptionContainer = storelessSubscriptionContainer,
getNetworkMode = getNetworkMode
getNetworkMode = getNetworkMode,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
@JvmStatic
@ -446,7 +449,9 @@ object EditorSessionModule {
updateBlocksMark: UpdateBlocksMark,
documentFileShareDownloader: DocumentFileShareDownloader,
clearBlockContent: ClearBlockContent,
clearBlockStyle: ClearBlockStyle
clearBlockStyle: ClearBlockStyle,
analyticsSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
spaceManager: SpaceManager
): Orchestrator = Orchestrator(
stores = storage,
createBlock = createBlock,
@ -488,7 +493,9 @@ object EditorSessionModule {
createTable = createTable,
fillTableRow = fillTableRow,
clearBlockContent = clearBlockContent,
clearBlockStyle = clearBlockStyle
clearBlockStyle = clearBlockStyle,
analyticsSpaceHelperDelegate = analyticsSpaceHelperDelegate,
spaceManager = spaceManager
)
}

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.linking.LinkToObjectViewModelFactory
import com.anytypeio.anytype.ui.linking.LinkToObjectFragment
import dagger.Module
@ -40,13 +41,15 @@ object LinkToObjectModule {
getObjectTypes: GetObjectTypes,
searchObjects: SearchObjects,
analytics: Analytics,
spaceManager: SpaceManager
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): LinkToObjectViewModelFactory = LinkToObjectViewModelFactory(
urlBuilder = urlBuilder,
getObjectTypes = getObjectTypes,
searchObjects = searchObjects,
analytics = analytics,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
@JvmStatic

View file

@ -7,6 +7,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.Editor
import com.anytypeio.anytype.presentation.linking.LinkToObjectOrWebViewModelFactory
import com.anytypeio.anytype.ui.linking.LinkToObjectOrWebPagesFragment
@ -42,7 +43,8 @@ object LinkToObjectOrWebModule {
analytics: Analytics,
stores: Editor.Storage,
urlValidator: UrlValidator,
spaceManager: SpaceManager
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): LinkToObjectOrWebViewModelFactory = LinkToObjectOrWebViewModelFactory(
urlBuilder = urlBuilder,
storeOfObjectTypes = storeOfObjectTypes,
@ -50,6 +52,7 @@ object LinkToObjectOrWebModule {
analytics = analytics,
stores = stores,
urlValidator = urlValidator,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
}

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.moving.MoveToViewModelFactory
import com.anytypeio.anytype.ui.moving.MoveToFragment
import dagger.Module
@ -53,12 +54,14 @@ object MoveToModule {
getObjectTypes: GetObjectTypes,
searchObjects: SearchObjects,
analytics: Analytics,
spaceManager: SpaceManager
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): MoveToViewModelFactory = MoveToViewModelFactory(
urlBuilder = urlBuilder,
getObjectTypes = getObjectTypes,
searchObjects = searchObjects,
analytics = analytics,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
}

View file

@ -25,6 +25,7 @@ import com.anytypeio.anytype.domain.templates.CreateTemplateFromObject
import com.anytypeio.anytype.domain.widgets.CreateWidget
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.other.DefaultDeepLinkResolver
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.editor.Editor
@ -127,7 +128,8 @@ object ObjectMenuModule {
debugGoroutinesShareDownloader: DebugGoroutinesShareDownloader,
createWidget: CreateWidget,
spaceManager: SpaceManager,
deepLinkResolver: DeepLinkResolver
deepLinkResolver: DeepLinkResolver,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): ObjectMenuViewModel.Factory = ObjectMenuViewModel.Factory(
setObjectIsArchived = setObjectIsArchived,
duplicateObject = duplicateObject,
@ -148,7 +150,8 @@ object ObjectMenuModule {
debugGoroutinesShareDownloader = debugGoroutinesShareDownloader,
createWidget = createWidget,
spaceManager = spaceManager,
deepLinkResolver = deepLinkResolver
deepLinkResolver = deepLinkResolver,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
@JvmStatic
@ -224,7 +227,8 @@ object ObjectSetMenuModule {
debugGoroutinesShareDownloader: DebugGoroutinesShareDownloader,
createWidget: CreateWidget,
spaceManager: SpaceManager,
deepLinkResolver: DeepLinkResolver
deepLinkResolver: DeepLinkResolver,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): ObjectSetMenuViewModel.Factory = ObjectSetMenuViewModel.Factory(
setObjectIsArchived = setObjectIsArchived,
addToFavorite = addToFavorite,
@ -241,7 +245,8 @@ object ObjectSetMenuModule {
debugGoroutinesShareDownloader = debugGoroutinesShareDownloader,
createWidget = createWidget,
spaceManager = spaceManager,
deepLinkResolver = deepLinkResolver
deepLinkResolver = deepLinkResolver,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
@JvmStatic

View file

@ -67,6 +67,7 @@ import com.anytypeio.anytype.domain.templates.GetTemplates
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
import com.anytypeio.anytype.domain.unsplash.UnsplashRepository
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
@ -252,7 +253,8 @@ object ObjectSetModule {
dispatchers: AppCoroutineDispatchers,
getNetworkMode: GetNetworkMode,
dateProvider: DateProvider,
permissions: UserPermissionProvider
permissions: UserPermissionProvider,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): ObjectSetViewModelFactory = ObjectSetViewModelFactory(
params = params,
openObjectSet = openObjectSet,
@ -294,7 +296,8 @@ object ObjectSetModule {
dispatchers = dispatchers,
getNetworkMode = getNetworkMode,
dateProvider = dateProvider,
permissions = permissions
permissions = permissions,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
@JvmStatic

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.search.ObjectSearchViewModelFactory
import com.anytypeio.anytype.ui.search.ObjectSearchFragment
import dagger.Module
@ -51,12 +52,14 @@ object ObjectSearchModule {
getObjectTypes: GetObjectTypes,
searchObjects: SearchObjects,
analytics: Analytics,
spaceManager: SpaceManager
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): ObjectSearchViewModelFactory = ObjectSearchViewModelFactory(
urlBuilder = urlBuilder,
searchObjects = searchObjects,
getObjectTypes = getObjectTypes,
analytics = analytics,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
}

View file

@ -29,6 +29,7 @@ import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
import com.anytypeio.anytype.domain.spaces.SpaceDeletedStatusWatcher
import com.anytypeio.anytype.domain.templates.GetTemplates
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.splash.SplashViewModelFactory
import com.anytypeio.anytype.ui.splash.SplashFragment
import dagger.Binds
@ -194,4 +195,5 @@ interface SplashDependencies : ComponentDependencies {
fun localeProvider(): LocaleProvider
fun awaitAccountStartManager(): AwaitAccountStartManager
fun userPermissionProvider(): UserPermissionProvider
fun analyticSpaceHelperDelegate(): AnalyticSpaceHelperDelegate
}

View file

@ -36,6 +36,7 @@ import com.anytypeio.anytype.domain.templates.GetTemplates
import com.anytypeio.anytype.domain.workspace.NotificationsChannel
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.home.HomeScreenViewModel
import com.anytypeio.anytype.presentation.home.Unsubscriber
import com.anytypeio.anytype.presentation.navigation.DeepLinkToObjectDelegate
@ -278,4 +279,5 @@ interface HomeScreenDependencies : ComponentDependencies {
fun userPermissionProvider(): UserPermissionProvider
fun notificationChannel(): NotificationsChannel
fun activeSpaceMembers() : ActiveSpaceMemberSubscriptionContainer
fun analyticSpaceHelperDelegate(): AnalyticSpaceHelperDelegate
}

View file

@ -22,6 +22,7 @@ import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
import com.anytypeio.anytype.domain.workspace.RemoveObjectsFromWorkspace
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.library.LibraryListDelegate
import com.anytypeio.anytype.presentation.library.LibraryResourceManager
import com.anytypeio.anytype.presentation.library.LibraryViewModel
@ -221,4 +222,5 @@ interface LibraryDependencies : ComponentDependencies {
fun logger(): Logger
fun container(): StorelessSubscriptionContainer
fun storeOfTypes (): StoreOfObjectTypes
fun analyticSpaceHelperDelegate(): AnalyticSpaceHelperDelegate
}

View file

@ -13,6 +13,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.multiplayer.SpaceInviteResolver
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.other.DefaultSpaceInviteResolver
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.multiplayer.RequestJoinSpaceViewModel
import com.anytypeio.anytype.ui.multiplayer.RequestJoinSpaceFragment
import dagger.Binds
@ -64,5 +65,6 @@ interface RequestJoinSpaceDependencies : ComponentDependencies {
fun dispatchers(): AppCoroutineDispatchers
fun spaceManager(): SpaceManager
fun logger(): Logger
fun anallytics(): Analytics
fun analytics(): Analytics
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -13,6 +13,7 @@ import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.multiplayer.ShareSpaceViewModel
import com.anytypeio.anytype.ui.multiplayer.ShareSpaceFragment
import dagger.Binds
@ -60,4 +61,5 @@ interface ShareSpaceDependencies : ComponentDependencies {
fun config(): ConfigStorage
fun permissions(): UserPermissionProvider
fun analytics(): Analytics
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -9,6 +9,7 @@ import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.multiplayer.SpaceJoinRequestViewModel
import com.anytypeio.anytype.ui.multiplayer.SpaceJoinRequestFragment
import dagger.Binds
@ -55,4 +56,5 @@ interface SpaceJoinRequestDependencies : ComponentDependencies {
fun dispatchers(): AppCoroutineDispatchers
fun spaceManager(): SpaceManager
fun analytics(): Analytics
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.UserSettingsRepository
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.notifications.NotificationsProvider
import com.anytypeio.anytype.presentation.notifications.NotificationsViewModelFactory
import com.anytypeio.anytype.ui.notifications.NotificationsFragment
@ -49,4 +50,5 @@ interface NotificationDependencies : ComponentDependencies {
fun spaceManager(): SpaceManager
fun userSettingsRepository(): UserSettingsRepository
fun provideDispatchers(): AppCoroutineDispatchers
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -8,9 +8,8 @@ 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.misc.AppActionManager
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.objects.SelectObjectTypeViewModel
import com.anytypeio.anytype.ui.objects.creation.SelectObjectTypeFragment
import dagger.Binds
@ -51,9 +50,8 @@ interface SelectObjectTypeDependencies : ComponentDependencies {
fun repo(): BlockRepository
fun analytics(): Analytics
fun dispatchers(): AppCoroutineDispatchers
fun spaceManager(): SpaceManager
fun userSettingsRepo(): UserSettingsRepository
fun configStorage(): ConfigStorage
fun appActionManager(): AppActionManager
fun storeOfObjectTypes(): StoreOfObjectTypes
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
fun userSettingsRepository(): UserSettingsRepository
fun provideSpaceManger(): SpaceManager
}

View file

@ -12,6 +12,7 @@ import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.GetRelations
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.relations.RelationAddToDataViewViewModel
import com.anytypeio.anytype.presentation.relations.RelationAddToObjectViewModel
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
@ -56,7 +57,8 @@ object RelationAddToObjectModule {
getRelations: GetRelations,
appCoroutineDispatchers: AppCoroutineDispatchers,
addObjectToWorkspace: AddObjectToWorkspace,
spaceManager: SpaceManager
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): RelationAddToObjectViewModel.Factory = RelationAddToObjectViewModel.Factory(
storeOfRelations = storeOfRelations,
addRelationToObject = addRelationToObject,
@ -66,7 +68,8 @@ object RelationAddToObjectModule {
getRelations = getRelations,
appCoroutineDispatchers = appCoroutineDispatchers,
addObjectToWorkspace = addObjectToWorkspace,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
@JvmStatic
@ -115,7 +118,8 @@ object RelationAddToDataViewModule {
appCoroutineDispatchers: AppCoroutineDispatchers,
getRelations: GetRelations,
addObjectToWorkspace: AddObjectToWorkspace,
spaceManager: SpaceManager
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): RelationAddToDataViewViewModel.Factory = RelationAddToDataViewViewModel.Factory(
addRelationToDataView = addRelationToDataView,
dispatcher = dispatcher,
@ -126,7 +130,8 @@ object RelationAddToDataViewModule {
appCoroutineDispatchers = appCoroutineDispatchers,
getRelations = getRelations,
addObjectToWorkspace = addObjectToWorkspace,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
@JvmStatic

View file

@ -12,6 +12,7 @@ import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.CreateRelation
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.relations.RelationCreateFromScratchForDataViewViewModel
import com.anytypeio.anytype.presentation.relations.RelationCreateFromScratchForObjectBlockViewModel
import com.anytypeio.anytype.presentation.relations.RelationCreateFromScratchForObjectViewModel
@ -55,14 +56,16 @@ object RelationCreateFromScratchForObjectModule {
analytics: Analytics,
createFromScratchState: StateHolder<CreateFromScratchState>,
createRelation: CreateRelation,
spaceManager: SpaceManager
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) = RelationCreateFromScratchForObjectViewModel.Factory(
addRelationToObject = addRelationToObject,
createRelation = createRelation,
dispatcher = dispatcher,
analytics = analytics,
createFromScratchState = createFromScratchState,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
@JvmStatic
@ -116,7 +119,8 @@ object RelationCreateFromScratchForDataViewModule {
createFromScratchState: StateHolder<CreateFromScratchState>,
createRelation: CreateRelation,
addRelationToDataView: AddRelationToDataView,
spaceManager: SpaceManager
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) = RelationCreateFromScratchForDataViewViewModel.Factory(
addRelationToDataView = addRelationToDataView,
dispatcher = dispatcher,
@ -125,7 +129,8 @@ object RelationCreateFromScratchForDataViewModule {
analytics = analytics,
createFromScratchState = createFromScratchState,
createRelation = createRelation,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
@JvmStatic
@ -182,14 +187,16 @@ object RelationCreateFromScratchForObjectBlockModule {
dispatcher: Dispatcher<Payload>,
analytics: Analytics,
createFromScratchState: StateHolder<CreateFromScratchState>,
spaceManager: SpaceManager
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) = RelationCreateFromScratchForObjectBlockViewModel.Factory(
addRelationToObject = addRelationToObject,
createRelation = createRelation,
dispatcher = dispatcher,
analytics = analytics,
createFromScratchState = createFromScratchState,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
@JvmStatic

View file

@ -4,9 +4,6 @@ import androidx.lifecycle.ViewModelProvider
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.emojifier.data.Emoji
import com.anytypeio.anytype.emojifier.data.EmojiProvider
import com.anytypeio.anytype.presentation.relations.RelationEditViewModel
import com.anytypeio.anytype.presentation.types.TypeIcon
import com.anytypeio.anytype.presentation.types.TypeId

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.auth.interactor.GetLibraryVersion
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.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.ui.settings.AboutAppFragment
import com.anytypeio.anytype.ui_settings.about.AboutAppViewModel
import dagger.Binds
@ -65,6 +66,7 @@ interface AboutAppDependencies : ComponentDependencies {
fun configStorage(): ConfigStorage
fun analytics(): Analytics
fun dispatchers(): AppCoroutineDispatchers
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}
@Scope

View file

@ -7,6 +7,7 @@ import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.config.UserSettingsRepository
import com.anytypeio.anytype.domain.theme.GetTheme
import com.anytypeio.anytype.domain.theme.SetTheme
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.ui.settings.AppearanceFragment
import com.anytypeio.anytype.ui_settings.appearance.AppearanceViewModel
import dagger.Component
@ -65,4 +66,5 @@ object AppearanceModule {
interface AppearanceDependencies : ComponentDependencies {
fun userUserSettingsRepository(): UserSettingsRepository
fun analytics(): Analytics
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -19,6 +19,7 @@ import com.anytypeio.anytype.domain.workspace.FileLimitsEventChannel
import com.anytypeio.anytype.domain.workspace.SpacesUsageInfo
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.settings.FilesStorageViewModel
import com.anytypeio.anytype.presentation.spaces.SpaceGradientProvider
import com.anytypeio.anytype.ui.settings.FilesStorageFragment
@ -120,4 +121,5 @@ interface FilesStorageDependencies : ComponentDependencies {
fun authRepo(): AuthRepository
fun logger(): Logger
fun spaceManager(): SpaceManager
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -16,6 +16,7 @@ import com.anytypeio.anytype.domain.workspace.FileLimitsEventChannel
import com.anytypeio.anytype.domain.workspace.SpacesUsageInfo
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.settings.SpacesStorageViewModelFactory
import com.anytypeio.anytype.ui.settings.SpacesStorageFragment
import dagger.Binds
@ -104,4 +105,5 @@ interface SpacesStorageDependencies : ComponentDependencies {
fun authRepo(): AuthRepository
fun logger(): Logger
fun spaceManager(): SpaceManager
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -14,6 +14,7 @@ import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.sharing.AddToAnytypeViewModel
import com.anytypeio.anytype.ui.sharing.SharingFragment
import dagger.Binds
@ -59,4 +60,5 @@ interface AddToAnytypeDependencies : ComponentDependencies {
fun analytics(): Analytics
fun fileSharer(): FileSharer
fun permissions(): UserPermissionProvider
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -7,6 +7,7 @@ import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.spaces.CreateSpaceViewModel
import com.anytypeio.anytype.presentation.spaces.SpaceGradientProvider
import com.anytypeio.anytype.ui.spaces.CreateSpaceFragment
@ -53,4 +54,5 @@ interface CreateSpaceDependencies : ComponentDependencies {
fun analytics(): Analytics
fun dispatchers(): AppCoroutineDispatchers
fun spaceManager(): SpaceManager
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -14,6 +14,7 @@ import com.anytypeio.anytype.domain.misc.AppActionManager
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.spaces.SelectSpaceViewModel
import com.anytypeio.anytype.presentation.spaces.SpaceGradientProvider
import com.anytypeio.anytype.ui.spaces.SelectSpaceFragment
@ -68,4 +69,5 @@ interface SelectSpaceDependencies : ComponentDependencies {
fun userSettings(): UserSettingsRepository
fun logger(): Logger
fun configStorage(): ConfigStorage
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -19,6 +19,7 @@ import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionCon
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.spaces.SpaceGradientProvider
import com.anytypeio.anytype.presentation.spaces.SpaceSettingsViewModel
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
@ -103,4 +104,5 @@ interface SpaceSettingsDependencies : ComponentDependencies {
fun userPermission(): UserPermissionProvider
fun spaceViewSubscriptionContainer(): SpaceViewSubscriptionContainer
fun activeSpaceMemberSubscriptionContainer(): ActiveSpaceMemberSubscriptionContainer
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -12,6 +12,7 @@ import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.templates.ApplyTemplate
import com.anytypeio.anytype.domain.templates.GetTemplates
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
import com.anytypeio.anytype.presentation.onboarding.OnboardingViewModel
import com.anytypeio.anytype.providers.DefaultCoverImageHashProvider
@ -83,6 +84,7 @@ interface TemplateSelectDependencies : ComponentDependencies {
fun blockRepository(): BlockRepository
fun dispatchers(): AppCoroutineDispatchers
fun spaceManager(): SpaceManager
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}
@Scope

View file

@ -11,6 +11,7 @@ import com.anytypeio.anytype.domain.types.CreateObjectType
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.emojifier.data.Emoji
import com.anytypeio.anytype.emojifier.data.EmojiProvider
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.types.CreateObjectTypeViewModel
import com.anytypeio.anytype.ui.types.create.CreateObjectTypeFragment
import dagger.Binds
@ -69,4 +70,5 @@ interface CreateObjectTypeDependencies : ComponentDependencies {
fun urlBuilder(): UrlBuilder
fun analytics(): Analytics
fun spaceManager(): SpaceManager
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.emojifier.data.Emoji
import com.anytypeio.anytype.emojifier.data.EmojiProvider
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.types.TypeEditViewModel
import com.anytypeio.anytype.presentation.types.TypeIcon
import com.anytypeio.anytype.presentation.types.TypeId
@ -72,4 +73,5 @@ interface TypeEditDependencies : ComponentDependencies {
fun blockRepository(): BlockRepository
fun urlBuilder(): UrlBuilder
fun analytics(): Analytics
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
}

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.util.Dispatcher
import com.anytypeio.anytype.presentation.widgets.SelectWidgetSourceViewModel
import com.anytypeio.anytype.presentation.widgets.WidgetDispatchEvent
@ -43,14 +44,16 @@ object SelectWidgetSourceModule {
searchObjects: SearchObjects,
getObjectTypes: GetObjectTypes,
dispatcher: Dispatcher<WidgetDispatchEvent>,
spaceManager: SpaceManager
spaceManager: SpaceManager,
analyticsHelper: AnalyticSpaceHelperDelegate
): SelectWidgetSourceViewModel.Factory = SelectWidgetSourceViewModel.Factory(
urlBuilder = urlBuilder,
searchObjects = searchObjects,
analytics = analytics,
getObjectTypes = getObjectTypes,
dispatcher = dispatcher,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticsHelper
)
@JvmStatic

View file

@ -3,6 +3,10 @@ package com.anytypeio.anytype.di.main
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.analytics.base.DefaultAnalytics
import com.anytypeio.anytype.analytics.tracker.AmplitudeTracker
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.analytics.DefaultAnalyticsParamsProvider
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.GlobalScope
@ -25,4 +29,15 @@ object AnalyticsModule {
scope = GlobalScope,
analytics = analytics
)
@JvmStatic
@Provides
@Singleton
fun provideAnalyticsParams(
userPermissionProvider: UserPermissionProvider,
spaceViewContainer: SpaceViewSubscriptionContainer
): AnalyticSpaceHelperDelegate = DefaultAnalyticsParamsProvider(
userPermissionProvider = userPermissionProvider,
spaceViewContainer = spaceViewContainer
)
}

View file

@ -32,6 +32,7 @@ import com.anytypeio.anytype.domain.search.ObjectSearchSubscriptionContainer
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
import com.anytypeio.anytype.domain.templates.GetTemplates
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.util.Dispatcher
import com.anytypeio.anytype.presentation.widgets.WidgetDispatchEvent
import com.anytypeio.anytype.presentation.widgets.collection.CollectionViewModel
@ -222,4 +223,5 @@ interface CollectionDependencies : ComponentDependencies {
fun logger(): Logger
fun dateProvider(): DateProvider
fun dateTypeNameProvider(): DateTypeNameProvider
fun analyticsHelperDelegate(): AnalyticSpaceHelperDelegate
}

View file

@ -36,6 +36,7 @@ interface SpaceViewSubscriptionContainer {
fun observe(space: SpaceId) : Flow<ObjectWrapper.SpaceView>
fun get(): List<ObjectWrapper.SpaceView>
fun get(space: SpaceId) : ObjectWrapper.SpaceView?
class Default @Inject constructor(
private val container: StorelessSubscriptionContainer,
@ -72,6 +73,10 @@ interface SpaceViewSubscriptionContainer {
return data.value
}
override fun get(space: SpaceId): ObjectWrapper.SpaceView? {
return data.value.find { spaceView -> spaceView.targetSpaceId == space.id }
}
override fun start() {
jobs += scope.launch(dispatchers.io) {
container.subscribe(

View file

@ -0,0 +1,52 @@
package com.anytypeio.anytype.presentation.analytics
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ext.EMPTY_STRING_VALUE
import com.anytypeio.anytype.core_models.multiplayer.SpaceAccessType
import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import javax.inject.Inject
interface AnalyticSpaceHelperDelegate {
fun provideParams(space: Id): Params
data class Params(
val permission: String,
val spaceType: String
) {
companion object {
val EMPTY = Params("", "")
}
}
}
class DefaultAnalyticsParamsProvider @Inject constructor(
private val userPermissionProvider: UserPermissionProvider,
private val spaceViewContainer: SpaceViewSubscriptionContainer
) : AnalyticSpaceHelperDelegate {
override fun provideParams(space: Id): AnalyticSpaceHelperDelegate.Params {
val spaceId = SpaceId(space)
val permissions = userPermissionProvider.get(spaceId)
val spaceType = spaceViewContainer.get(spaceId)?.spaceAccessType
return AnalyticSpaceHelperDelegate.Params(
permission = when (permissions) {
SpaceMemberPermissions.READER -> "Reader"
SpaceMemberPermissions.WRITER -> "Writer"
SpaceMemberPermissions.OWNER -> "Owner"
SpaceMemberPermissions.NO_PERMISSIONS -> "NoPermissions"
null -> EMPTY_STRING_VALUE
},
spaceType = when (spaceType) {
SpaceAccessType.DEFAULT -> "Personal"
SpaceAccessType.PRIVATE -> "Private"
SpaceAccessType.SHARED -> "Shared"
else -> EMPTY_STRING_VALUE
}
)
}
}

View file

@ -101,6 +101,7 @@ import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.BuildConfig
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.common.StateReducer
@ -278,7 +279,7 @@ import timber.log.Timber
import com.anytypeio.anytype.presentation.editor.Editor.Mode as EditorMode
class EditorViewModel(
private val params: Params,
private val vmParams: Params,
private val permissions: UserPermissionProvider,
private val openPage: OpenPage,
private val closePage: CloseBlock,
@ -320,7 +321,8 @@ class EditorViewModel(
private val templatesContainer: ObjectTypeTemplatesContainer,
private val storelessSubscriptionContainer: StorelessSubscriptionContainer,
private val dispatchers: AppCoroutineDispatchers,
private val getNetworkMode: GetNetworkMode
private val getNetworkMode: GetNetworkMode,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewStateViewModel<ViewState>(),
PickerListener,
SupportNavigation<EventWrapper<AppNavigation.Command>>,
@ -329,7 +331,8 @@ class EditorViewModel(
ToggleStateHolder by renderer,
SelectionStateHolder by orchestrator.memory.selections,
EditorTableDelegate by tableDelegate,
StateReducer<List<Block>, Event> by reducer {
StateReducer<List<Block>, Event> by reducer,
AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
val actions = MutableStateFlow(ActionItemType.defaultSorting)
@ -405,7 +408,7 @@ class EditorViewModel(
override val navigation = MutableLiveData<EventWrapper<AppNavigation.Command>>()
override val commands = MutableLiveData<EventWrapper<Command>>()
val permission = MutableStateFlow(permissions.get(params.space))
val permission = MutableStateFlow(permissions.get(vmParams.space))
init {
proceedWithObservingPermissions()
@ -417,7 +420,7 @@ class EditorViewModel(
startObservingErrors()
processRendering()
processMarkupChanges()
viewModelScope.launch { orchestrator.start() }
viewModelScope.launch { orchestrator.start(vmParams.space) }
viewModelScope.launch {
delegator.receive().collect { action ->
@ -445,7 +448,7 @@ class EditorViewModel(
private fun proceedWithObservingPermissions() {
viewModelScope.launch {
permissions
.observe(space = params.space)
.observe(space = vmParams.space)
.collect {
permission.value = it
}
@ -514,7 +517,7 @@ class EditorViewModel(
downloadUnsplashImage(
DownloadUnsplashImage.Params(
picture = action.img,
space = params.space
space = vmParams.space
)
).process(
failure = {
@ -717,7 +720,7 @@ class EditorViewModel(
proceedWithUpdatingText(
intent = Intent.Text.UpdateText(
context = params.ctx,
context = vmParams.ctx,
target = new.id,
text = new.content<Content.Text>().text,
marks = new.content<Content.Text>().marks
@ -1042,7 +1045,7 @@ class EditorViewModel(
.build(InterceptThreadStatus.Params(context))
.collect { status ->
val statusView = status.toView(
networkId = spaceManager.getConfig(space = params.space)?.network,
networkId = spaceManager.getConfig(space = vmParams.space)?.network,
networkMode = networkMode
)
syncStatus.value = statusView
@ -1082,6 +1085,7 @@ class EditorViewModel(
startTime = startTime,
details = orchestrator.stores.details.current().details,
ctx = context,
spaceParams = provideParams(vmParams.space.id)
)
}
}
@ -1383,15 +1387,6 @@ class EditorViewModel(
Editor.Focus.id(id = id, isPending = false)
)
}
// controlPanelInteractor.onEvent(
// ControlPanelMachine.Event.OnFocusChanged(
// id = id,
// style = if (id == context)
// Content.Text.Style.TITLE
// else
// blocks.first { it.id == id }.textStyle()
// )
// )
}
}
@ -1737,7 +1732,7 @@ class EditorViewModel(
viewModelScope.launch {
orchestrator.proxies.intents.send(
Intent.CRUD.Create(
context = params.ctx,
context = vmParams.ctx,
target = target,
position = position,
prototype = Prototype.Text(style = style)
@ -3153,9 +3148,9 @@ class EditorViewModel(
val detail = details.details[dv.targetObjectId]
if (detail != null && detail.map.isNotEmpty()) {
val wrapper = ObjectWrapper.Basic(detail.map)
wrapper.spaceId ?: params.space.id
wrapper.spaceId ?: vmParams.space.id
} else {
params.space.id
vmParams.space.id
}
}
proceedWithOpeningDataViewObject(
@ -3255,7 +3250,7 @@ class EditorViewModel(
typeId = TypeId(objectTypeView.id),
typeKey = TypeKey(objectTypeView.key),
template = objectTypeView.defaultTemplate,
space = params.space.id
space = vmParams.space.id
)
createBlockLinkWithObject.async(
params = params
@ -3265,12 +3260,14 @@ class EditorViewModel(
},
onSuccess = { result ->
orchestrator.proxies.payloads.send(result.payload)
sendAnalyticsCreateLink(analytics)
val spaceParams = provideParams(vmParams.space.id)
sendAnalyticsCreateLink(analytics, spaceParams)
sendAnalyticsObjectCreateEvent(
analytics = analytics,
route = EventsDictionary.Routes.objPowerTool,
startTime = startTime,
objType = storeOfObjectTypes.getByKey(objectTypeView.key)
objType = storeOfObjectTypes.getByKey(objectTypeView.key),
spaceParams = spaceParams
)
proceedWithOpeningObject(result.objectId)
}
@ -3288,7 +3285,7 @@ class EditorViewModel(
Timber.d("onProceedWithApplyingTemplateByObjectId, template:[$template]")
viewModelScope.launch {
val params = ApplyTemplate.Params(
ctx = params.ctx,
ctx = vmParams.ctx,
template = template,
)
applyTemplate.async(params = params).fold(
@ -3314,7 +3311,8 @@ class EditorViewModel(
route = EventsDictionary.Routes.navigation,
startTime = startTime,
objType = objType ?: storeOfObjectTypes.getByKey(result.typeKey.key),
view = EventsDictionary.View.viewNavbar
view = EventsDictionary.View.viewNavbar,
spaceParams = provideParams(vmParams.space.id)
)
proceedWithCloseCurrentAndOpenObject(result.obj)
},
@ -4070,7 +4068,7 @@ class EditorViewModel(
type = relation.type,
filters = ObjectSearchConstants.setsByObjectTypeFilters(
types = listOf(relation.type),
space = this@EditorViewModel.params.space.id
space = vmParams.space.id
)
)
findObjectSetForType(params).process(
@ -4297,12 +4295,12 @@ class EditorViewModel(
onFailure = {
Timber.e(it, "Error while closing object")
navigate(EventWrapper(
AppNavigation.Command.OpenObject(target = target, space = params.space.id))
AppNavigation.Command.OpenObject(target = target, space = vmParams.space.id))
)
},
onSuccess = {
navigate(EventWrapper(
AppNavigation.Command.OpenObject(target = target, space = params.space.id))
AppNavigation.Command.OpenObject(target = target, space = vmParams.space.id))
)
}
)
@ -4355,7 +4353,7 @@ class EditorViewModel(
isPopUpToDashboard: Boolean = false
) {
viewModelScope.launch {
closePage.async(params.ctx).fold(
closePage.async(vmParams.ctx).fold(
onFailure = {
Timber.e(it, "Error while closing object")
navigate(
@ -4529,8 +4527,8 @@ class EditorViewModel(
onFailure = { error -> Timber.e(error, "Error convert object to set") },
onSuccess = {
proceedWithOpeningDataViewObject(
target = params.ctx,
space = params.space,
target = vmParams.ctx,
space = vmParams.space,
isPopUpToDashboard = true
)
viewModelScope.sendAnalyticsObjectTypeSelectOrChangeEvent(
@ -4539,6 +4537,7 @@ class EditorViewModel(
sourceObject = SET_MARKETPLACE_ID,
containsFlagType = true,
route = EventsDictionary.Routes.navigation,
spaceParams = provideParams(vmParams.space.id)
)
}
)
@ -4552,8 +4551,8 @@ class EditorViewModel(
onFailure = { error -> Timber.e(error, "Error convert object to collection") },
onSuccess = {
proceedWithOpeningDataViewObject(
target = params.ctx,
space = params.space,
target = vmParams.ctx,
space = vmParams.space,
isPopUpToDashboard = true
)
viewModelScope.sendAnalyticsObjectTypeSelectOrChangeEvent(
@ -5014,7 +5013,7 @@ class EditorViewModel(
}
val intent = Intent.Text.UpdateText(
context = params.ctx,
context = vmParams.ctx,
target = targetId,
text = text,
marks = marks
@ -5045,7 +5044,7 @@ class EditorViewModel(
sorts = sorts,
filters = ObjectSearchConstants.filterTypes(
spaces = buildList {
add(params.space.id)
add(vmParams.space.id)
},
recommendedLayouts = SupportedLayouts.editorLayouts
),
@ -5955,7 +5954,8 @@ class EditorViewModel(
analytics = analytics,
route = EventsDictionary.Routes.objCreateMention,
startTime = startTime,
objType = storeOfObjectTypes.getByKey(typeKey.key)
objType = storeOfObjectTypes.getByKey(typeKey.key),
spaceParams = provideParams(vmParams.space.id)
)
}
)
@ -5967,7 +5967,8 @@ class EditorViewModel(
viewModelScope.sendAnalyticsSearchResultEvent(
analytics = analytics,
pos = pos,
length = mentionTrigger.length - 1
length = mentionTrigger.length - 1,
spaceParams = provideParams(vmParams.space.id)
)
onCreateMentionInText(id = mention.id, name = mention.name, mentionTrigger = mentionTrigger)
}
@ -6035,8 +6036,8 @@ class EditorViewModel(
filters = ObjectSearchConstants.getFilterLinkTo(
ignore = context,
spaces = buildList {
add(params.space.id)
val config = spaceManager.getConfig(params.space)
add(vmParams.space.id)
val config = spaceManager.getConfig(vmParams.space)
if (config != null) add(config.techSpace)
},
),
@ -6147,7 +6148,7 @@ class EditorViewModel(
sorts = emptyList(),
filters = ObjectSearchConstants.filterTypes(
spaces = buildList {
add(params.space.id)
add(vmParams.space.id)
},
recommendedLayouts = SupportedLayouts.createObjectLayouts
),
@ -6200,7 +6201,7 @@ class EditorViewModel(
viewModelScope.launch {
setObjectType.async(
SetObjectType.Params(
context = params.ctx,
context = vmParams.ctx,
objectTypeKey = objType.uniqueKey
)
).fold(
@ -6255,14 +6256,14 @@ class EditorViewModel(
createObjectSet(
CreateObjectSet.Params(
type = type,
space = params.space.id
space = vmParams.space.id
)
).process(
failure = { Timber.e(it, "Error while creating a set of type: $type") },
success = { response ->
proceedWithOpeningDataViewObject(
target = response.target,
space = params.space
space = vmParams.space
)
}
)
@ -6328,7 +6329,8 @@ class EditorViewModel(
analytics = analytics,
route = EventsDictionary.Routes.objLink,
startTime = startTime,
objType = storeOfObjectTypes.getByKey(typeKey.key)
objType = storeOfObjectTypes.getByKey(typeKey.key),
spaceParams = provideParams(vmParams.space.id)
)
}
)
@ -6515,7 +6517,7 @@ class EditorViewModel(
.subscribeToTemplates(
type = objType.id,
subscription = EDITOR_TEMPLATES_SUBSCRIPTION,
space = params.space
space = vmParams.space
)
.catch { Timber.e(it, "Error while subscribing to templates") }
.collect { templates ->

View file

@ -6,7 +6,6 @@ import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions
import com.anytypeio.anytype.core_utils.tools.FeatureToggles
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.interactor.RemoveLinkMark
@ -40,6 +39,7 @@ import com.anytypeio.anytype.domain.templates.ApplyTemplate
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.common.StateReducer
@ -94,13 +94,14 @@ open class EditorViewModelFactory @Inject constructor(
private val templatesContainer: ObjectTypeTemplatesContainer,
private val storelessSubscriptionContainer: StorelessSubscriptionContainer,
private val dispatchers: AppCoroutineDispatchers,
private val getNetworkMode: GetNetworkMode
private val getNetworkMode: GetNetworkMode,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return EditorViewModel(
params = params,
vmParams = params,
permissions = permissions,
openPage = openPage,
closePage = closeObject,
@ -142,7 +143,8 @@ open class EditorViewModelFactory @Inject constructor(
templatesContainer = templatesContainer,
dispatchers = dispatchers,
storelessSubscriptionContainer = storelessSubscriptionContainer,
getNetworkMode = getNetworkMode
getNetworkMode = getNetworkMode,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -3,6 +3,7 @@ package com.anytypeio.anytype.presentation.editor.editor
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.analytics.event.EventAnalytics
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.suspendFold
import com.anytypeio.anytype.domain.block.UpdateDivider
import com.anytypeio.anytype.domain.block.interactor.ClearBlockContent
@ -37,6 +38,8 @@ import com.anytypeio.anytype.domain.page.bookmark.SetupBookmark
import com.anytypeio.anytype.domain.relations.SetRelationKey
import com.anytypeio.anytype.domain.table.CreateTable
import com.anytypeio.anytype.domain.table.FillTableRow
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.Editor
import com.anytypeio.anytype.presentation.extension.sendAnalyticsChangeTextBlockStyleEvent
import com.anytypeio.anytype.presentation.extension.sendAnalyticsCopyBlockEvent
@ -91,13 +94,16 @@ class Orchestrator(
val textInteractor: Interactor.TextInteractor,
private val analytics: Analytics,
private val clearBlockContent: ClearBlockContent,
private val clearBlockStyle: ClearBlockStyle
) {
private val clearBlockStyle: ClearBlockStyle,
private val analyticsSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
private val spaceManager: SpaceManager
) : AnalyticSpaceHelperDelegate by analyticsSpaceHelperDelegate {
private val defaultOnError: suspend (Throwable) -> Unit = { Timber.e(it) }
suspend fun start() {
suspend fun start(space: SpaceId) {
proxies.intents.stream().collect { intent ->
val spaceParams = provideParams(space.id)
when (intent) {
is Intent.CRUD.Create -> {
val startTime = System.currentTimeMillis()
@ -117,7 +123,8 @@ class Orchestrator(
analytics.sendAnalyticsCreateBlockEvent(
prototype = intent.prototype,
startTime = startTime,
middlewareTime = middlewareTime
middlewareTime = middlewareTime,
spaceParams = spaceParams
)
},
onFailure = defaultOnError
@ -140,7 +147,8 @@ class Orchestrator(
analytics.sendAnalyticsCreateBlockEvent(
prototype = intent.prototype,
startTime = startTime,
middlewareTime = middlewareTime
middlewareTime = middlewareTime,
spaceParams = spaceParams
)
}
)
@ -226,7 +234,8 @@ class Orchestrator(
analytics.sendAnalyticsSplitBlockEvent(
startTime = startTime,
middlewareTime = middlewareTime,
style = intent.style
style = intent.style,
spaceParams = spaceParams
)
}
)
@ -511,7 +520,8 @@ class Orchestrator(
analytics.sendAnalyticsCreateBlockEvent(
prototype = Block.Prototype.Bookmark.New,
startTime = startTime,
middlewareTime = middlewareTime
middlewareTime = middlewareTime,
spaceParams = spaceParams
)
}
)
@ -607,7 +617,8 @@ class Orchestrator(
analytics.sendAnalyticsCreateBlockEvent(
prototype = Block.Prototype.SimpleTable,
startTime = startTime,
middlewareTime = middlewareTime
middlewareTime = middlewareTime,
spaceParams = spaceParams
)
}
)

View file

@ -48,6 +48,7 @@ import com.anytypeio.anytype.core_models.WidgetLayout
import com.anytypeio.anytype.core_models.ext.mapToObjectWrapperType
import com.anytypeio.anytype.core_utils.ext.Mimetype
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.editor.Markup
import com.anytypeio.anytype.presentation.sets.isChangingDefaultTypeAvailable
import com.anytypeio.anytype.presentation.sets.state.ObjectState
@ -60,14 +61,18 @@ fun Block.Prototype.getAnalyticsEvent(
eventName: String,
startTime: Long,
middlewareTime: Long,
renderTime: Long
renderTime: Long,
spaceParams: AnalyticSpaceHelperDelegate.Params
): EventAnalytics.Anytype {
val props = when (this) {
is Block.Prototype.Text -> {
Props(
mapOf(
EventsPropertiesKey.type to "text",
EventsPropertiesKey.style to getStyleName()
EventsPropertiesKey.style to getStyleName(),
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
}
@ -75,7 +80,9 @@ fun Block.Prototype.getAnalyticsEvent(
Props(
mapOf(
EventsPropertiesKey.type to getTypePropName(),
EventsPropertiesKey.style to "Embed"
EventsPropertiesKey.style to "Embed",
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
}
@ -86,17 +93,29 @@ fun Block.Prototype.getAnalyticsEvent(
start = startTime,
middleware = middlewareTime,
render = renderTime
),
props = Props(
mapOf(
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
)
}
is Block.Prototype.Relation -> {
Props(mapOf(EventsPropertiesKey.type to "relation"))
Props(mapOf(
EventsPropertiesKey.type to "relation",
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
))
}
is Block.Prototype.DividerLine -> {
Props(
mapOf(
EventsPropertiesKey.type to "div",
EventsPropertiesKey.style to "line"
EventsPropertiesKey.style to "line",
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
}
@ -104,21 +123,39 @@ fun Block.Prototype.getAnalyticsEvent(
Props(
mapOf(
EventsPropertiesKey.type to "div",
EventsPropertiesKey.style to "dots"
EventsPropertiesKey.style to "dots",
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
}
is Block.Prototype.Bookmark -> {
Props(mapOf(EventsPropertiesKey.type to "bookmark"))
Props(mapOf(
EventsPropertiesKey.type to "bookmark",
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
))
}
is Block.Prototype.Latex -> {
Props(mapOf(EventsPropertiesKey.type to "latex"))
Props(mapOf(
EventsPropertiesKey.type to "latex",
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
))
}
is Block.Prototype.TableOfContents -> {
Props(mapOf(EventsPropertiesKey.type to "table_of_contents"))
Props(mapOf(
EventsPropertiesKey.type to "table_of_contents",
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
))
}
is Block.Prototype.SimpleTable -> {
Props(mapOf(EventsPropertiesKey.type to "table"))
Props(mapOf(
EventsPropertiesKey.type to "table",
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
))
}
}
@ -240,7 +277,8 @@ fun CoroutineScope.sendAnalyticsObjectShowEvent(
ctx: Id,
details: Map<Id, Block.Fields>?,
analytics: Analytics,
startTime: Long
startTime: Long,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
val objType = getAnalyticsObjectType(
details = details,
@ -249,6 +287,8 @@ fun CoroutineScope.sendAnalyticsObjectShowEvent(
val props = Props(
mapOf(
EventsPropertiesKey.objectType to objType,
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
sendEvent(
@ -269,7 +309,8 @@ fun CoroutineScope.sendAnalyticsObjectShowEvent(
fun CoroutineScope.sendAnalyticsSearchResultEvent(
analytics: Analytics,
pos: Int,
length: Int
length: Int,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
sendEvent(
analytics = analytics,
@ -277,7 +318,9 @@ fun CoroutineScope.sendAnalyticsSearchResultEvent(
props = Props(
mapOf(
EventsPropertiesKey.index to pos,
EventsPropertiesKey.length to length
EventsPropertiesKey.length to length,
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
)
@ -336,11 +379,14 @@ fun CoroutineScope.sendAnalyticsRemoveFromFavoritesEvent(
fun CoroutineScope.sendAnalyticsBackLinkAddEvent(
analytics: Analytics,
startTime: Long
startTime: Long,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
val props = Props(
buildMap {
put("linkType", "Object")
put(EventsPropertiesKey.permissions, spaceParams.permission)
put(EventsPropertiesKey.spaceType, spaceParams.spaceType)
}
)
sendEvent(
@ -384,7 +430,8 @@ fun CoroutineScope.sendAnalyticsDuplicateEvent(
details: Map<Id, Block.Fields>?,
ctx: Id,
startTime: Long,
count: Int = 1
count: Int = 1,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
val objType = getAnalyticsObjectType(
details = details,
@ -393,7 +440,9 @@ fun CoroutineScope.sendAnalyticsDuplicateEvent(
val props = Props(
mapOf(
EventsPropertiesKey.count to count,
EventsPropertiesKey.objectType to objType
EventsPropertiesKey.objectType to objType,
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
sendEvent(
@ -406,14 +455,19 @@ fun CoroutineScope.sendAnalyticsDuplicateEvent(
}
suspend fun Analytics.sendAnalyticsSplitBlockEvent(
style: TextStyle, startTime: Long, middlewareTime: Long
style: TextStyle,
startTime: Long,
middlewareTime: Long,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
val event = EventAnalytics.Anytype(
name = EventsDictionary.blockCreate,
props = Props(
mapOf(
EventsPropertiesKey.type to "text",
EventsPropertiesKey.style to style.getStyleName()
EventsPropertiesKey.style to style.getStyleName(),
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
),
duration = EventAnalytics.Duration(
@ -426,13 +480,17 @@ suspend fun Analytics.sendAnalyticsSplitBlockEvent(
}
suspend fun Analytics.sendAnalyticsCreateBlockEvent(
prototype: Block.Prototype, startTime: Long, middlewareTime: Long
prototype: Block.Prototype,
startTime: Long,
middlewareTime: Long,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
val event = prototype.getAnalyticsEvent(
eventName = EventsDictionary.blockCreate,
startTime = startTime,
middlewareTime = middlewareTime,
renderTime = System.currentTimeMillis()
renderTime = System.currentTimeMillis(),
spaceParams = spaceParams
)
registerEvent(event)
}
@ -580,13 +638,16 @@ fun CoroutineScope.sendAnalyticsObjectTypeSelectOrChangeEvent(
startTime: Long,
sourceObject: Id? = null,
containsFlagType: Boolean,
route: String? = null
route: String? = null,
spaceParams: AnalyticSpaceHelperDelegate.Params? = null
) {
val objType = sourceObject ?: OBJ_TYPE_CUSTOM
val props = Props(
mapOf(
EventsPropertiesKey.objectType to objType,
EventsPropertiesKey.route to route
EventsPropertiesKey.route to route,
EventsPropertiesKey.permissions to spaceParams?.permission,
EventsPropertiesKey.spaceType to spaceParams?.spaceType
)
)
val event = if (containsFlagType) {
@ -614,7 +675,8 @@ suspend fun Analytics.sendAnalyticsObjectLayoutChangeEvent(name: String) {
fun CoroutineScope.sendAnalyticsCreateRelationEvent(
analytics: Analytics,
format: String,
type: String
type: String,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
sendEvent(
analytics = analytics,
@ -622,7 +684,9 @@ fun CoroutineScope.sendAnalyticsCreateRelationEvent(
props = Props(
mapOf(
EventsPropertiesKey.format to format,
EventsPropertiesKey.type to type
EventsPropertiesKey.type to type,
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
)
@ -631,7 +695,8 @@ fun CoroutineScope.sendAnalyticsCreateRelationEvent(
fun CoroutineScope.sendAnalyticsAddRelationEvent(
analytics: Analytics,
format: String,
type: String
type: String,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
sendEvent(
analytics = analytics,
@ -639,7 +704,9 @@ fun CoroutineScope.sendAnalyticsAddRelationEvent(
props = Props(
mapOf(
EventsPropertiesKey.format to format,
EventsPropertiesKey.type to type
EventsPropertiesKey.type to type,
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
)
@ -674,13 +741,16 @@ fun CoroutineScope.sendAnalyticsObjectCreateEvent(
route: String,
startTime: Long? = null,
view: String? = null,
objType: String?
objType: String?,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
val props = Props(
mapOf(
EventsPropertiesKey.objectType to objType,
EventsPropertiesKey.route to route,
EventsPropertiesKey.view to view
EventsPropertiesKey.view to view,
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
sendEvent(
@ -697,7 +767,8 @@ fun CoroutineScope.sendAnalyticsObjectCreateEvent(
route: String,
startTime: Long? = null,
view: String? = null,
objType: ObjectWrapper.Type?
objType: ObjectWrapper.Type?,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
val objTypeParam = if (objType == null) null
else objType.sourceObject ?: OBJ_TYPE_CUSTOM
@ -705,7 +776,9 @@ fun CoroutineScope.sendAnalyticsObjectCreateEvent(
mapOf(
EventsPropertiesKey.objectType to objTypeParam,
EventsPropertiesKey.route to route,
EventsPropertiesKey.view to view
EventsPropertiesKey.view to view,
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
sendEvent(
@ -925,7 +998,8 @@ fun CoroutineScope.logEvent(
startTime: Long? = null,
type: String? = null,
condition: DVFilterCondition? = null,
currentViewId: Id? = null
currentViewId: Id? = null,
spaceParams: AnalyticSpaceHelperDelegate.Params = AnalyticSpaceHelperDelegate.Params.EMPTY
) {
if (state !is ObjectState.DataView) return
val middleTime = System.currentTimeMillis()
@ -950,6 +1024,7 @@ fun CoroutineScope.logEvent(
middleTime = middleTime,
props = buildProps(
type = viewerType,
spaceParams = spaceParams
)
)
is ObjectState.DataView.Set -> scope.sendEvent(
@ -960,6 +1035,7 @@ fun CoroutineScope.logEvent(
props = buildProps(
embedType = embedTypeDefault,
type = viewerType,
spaceParams = spaceParams
)
)
}
@ -969,7 +1045,10 @@ fun CoroutineScope.logEvent(
analytics = analytics,
eventName = turnIntoCollection,
startTime = startTime,
middleTime = middleTime
middleTime = middleTime,
props = buildProps(
spaceParams = spaceParams
)
)
}
ObjectStateAnalyticsEvent.SELECT_QUERY -> {
@ -978,7 +1057,7 @@ fun CoroutineScope.logEvent(
eventName = setSelectQuery,
startTime = startTime,
middleTime = middleTime,
props = buildProps(type = type)
props = buildProps(type = type, spaceParams = spaceParams)
)
}
ObjectStateAnalyticsEvent.ADD_VIEW -> {
@ -990,7 +1069,8 @@ fun CoroutineScope.logEvent(
props = buildProps(
type = type,
embedType = embedTypeDefault,
objectType = objectTypeDefault
objectType = objectTypeDefault,
spaceParams = spaceParams
)
)
}
@ -1003,7 +1083,8 @@ fun CoroutineScope.logEvent(
props = buildProps(
type = type,
embedType = embedTypeDefault,
objectType = objectTypeDefault
objectType = objectTypeDefault,
spaceParams = spaceParams
)
)
}
@ -1015,7 +1096,8 @@ fun CoroutineScope.logEvent(
middleTime = middleTime,
props = buildProps(
embedType = embedTypeDefault,
objectType = objectTypeDefault
objectType = objectTypeDefault,
spaceParams = spaceParams
)
)
}
@ -1028,7 +1110,8 @@ fun CoroutineScope.logEvent(
props = buildProps(
type = type,
embedType = embedTypeDefault,
objectType = objectTypeDefault
objectType = objectTypeDefault,
spaceParams = spaceParams
)
)
}
@ -1041,7 +1124,8 @@ fun CoroutineScope.logEvent(
props = buildProps(
type = type,
embedType = embedTypeDefault,
objectType = objectTypeDefault
objectType = objectTypeDefault,
spaceParams = spaceParams
)
)
}
@ -1054,7 +1138,8 @@ fun CoroutineScope.logEvent(
props = buildProps(
type = type,
embedType = embedTypeDefault,
objectType = objectTypeDefault
objectType = objectTypeDefault,
spaceParams = spaceParams
)
)
}
@ -1067,7 +1152,8 @@ fun CoroutineScope.logEvent(
props = buildProps(
embedType = embedTypeDefault,
objectType = objectTypeDefault,
condition = condition
condition = condition,
spaceParams = spaceParams
)
)
}
@ -1080,7 +1166,8 @@ fun CoroutineScope.logEvent(
props = buildProps(
embedType = embedTypeDefault,
objectType = objectTypeDefault,
condition = condition
condition = condition,
spaceParams = spaceParams
)
)
}
@ -1092,7 +1179,8 @@ fun CoroutineScope.logEvent(
middleTime = middleTime,
props = buildProps(
embedType = embedTypeDefault,
objectType = objectTypeDefault
objectType = objectTypeDefault,
spaceParams = spaceParams
)
)
}
@ -1105,7 +1193,8 @@ fun CoroutineScope.logEvent(
props = buildProps(
embedType = embedTypeDefault,
objectType = objectTypeDefault,
type = type
type = type,
spaceParams = spaceParams
)
)
}
@ -1118,7 +1207,8 @@ fun CoroutineScope.logEvent(
props = buildProps(
embedType = embedTypeDefault,
objectType = objectTypeDefault,
type = type
type = type,
spaceParams = spaceParams
)
)
}
@ -1130,7 +1220,8 @@ fun CoroutineScope.logEvent(
middleTime = middleTime,
props = buildProps(
embedType = embedTypeDefault,
objectType = objectTypeDefault
objectType = objectTypeDefault,
spaceParams = spaceParams
)
)
}
@ -1146,7 +1237,8 @@ fun CoroutineScope.logEvent(
middleTime = middleTime,
props = buildProps(
objectType = type,
route = route
route = route,
spaceParams = spaceParams
)
)
}
@ -1162,7 +1254,8 @@ fun CoroutineScope.logEvent(
startTime = startTime,
middleTime = middleTime,
props = buildProps(
route = route
route = route,
spaceParams = spaceParams
)
)
}
@ -1177,7 +1270,8 @@ fun CoroutineScope.logEvent(
startTime = startTime,
middleTime = middleTime,
props = buildProps(
route = route
route = route,
spaceParams = spaceParams
)
)
}
@ -1193,7 +1287,8 @@ fun CoroutineScope.logEvent(
middleTime = middleTime,
props = buildProps(
route = route,
objectType = type ?: OBJ_TYPE_CUSTOM
objectType = type ?: OBJ_TYPE_CUSTOM,
spaceParams = spaceParams
)
)
}
@ -1210,7 +1305,8 @@ fun CoroutineScope.logEvent(
middleTime = middleTime,
props = buildProps(
route = route,
objectType = type ?: OBJ_TYPE_CUSTOM
objectType = type ?: OBJ_TYPE_CUSTOM,
spaceParams = spaceParams
)
)
}
@ -1227,7 +1323,8 @@ fun CoroutineScope.logEvent(
middleTime = middleTime,
props = buildProps(
route = route,
objectType = type ?: OBJ_TYPE_CUSTOM
objectType = type ?: OBJ_TYPE_CUSTOM,
spaceParams = spaceParams
)
)
}
@ -1244,7 +1341,8 @@ fun CoroutineScope.logEvent(
middleTime = middleTime,
props = buildProps(
route = route,
objectType = type ?: OBJ_TYPE_CUSTOM
objectType = type ?: OBJ_TYPE_CUSTOM,
spaceParams = spaceParams
)
)
}
@ -1262,7 +1360,8 @@ fun CoroutineScope.logEvent(
middleTime = middleTime,
props = buildProps(
route = route,
objectType = type ?: OBJ_TYPE_CUSTOM
objectType = type ?: OBJ_TYPE_CUSTOM,
spaceParams = spaceParams
)
)
}
@ -1278,7 +1377,7 @@ fun CoroutineScope.logEvent(
eventName = changeDefaultTemplate,
startTime = startTime,
middleTime = middleTime,
props = buildProps(route = route)
props = buildProps(route = route, spaceParams = spaceParams)
)
}
}
@ -1289,7 +1388,8 @@ private fun buildProps(
type: String? = null,
objectType: String? = null,
condition: DVFilterCondition? = null,
route: String? = null
route: String? = null,
spaceParams: AnalyticSpaceHelperDelegate.Params
): Props {
return Props(
map = buildMap {
@ -1298,6 +1398,14 @@ private fun buildProps(
if (objectType != null) put("objectType", objectType)
if (condition != null) put("condition", condition.getPropName())
if (route != null) put("route", route)
if (spaceParams.permission.isNotEmpty()) put(
EventsPropertiesKey.permissions,
spaceParams.permission
)
if (spaceParams.spaceType.isNotEmpty()) put(
EventsPropertiesKey.spaceType,
spaceParams.spaceType
)
}
)
}
@ -1808,7 +1916,8 @@ fun CoroutineScope.sendAnalyticsCreateTemplateEvent(
analytics: Analytics,
details: Map<Id, Block.Fields>,
ctx: Id,
startTime: Long
startTime: Long,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
val objType = getAnalyticsObjectType(
details = details,
@ -1821,6 +1930,8 @@ fun CoroutineScope.sendAnalyticsCreateTemplateEvent(
buildMap {
put(EventsPropertiesKey.route, "MenuObject")
put(EventsPropertiesKey.objectType, objType)
put(EventsPropertiesKey.permissions, spaceParams.permission)
put(EventsPropertiesKey.spaceType, spaceParams.spaceType)
}
),
startTime = startTime,
@ -1861,11 +1972,18 @@ private fun getAnalyticsObjectType(
}
fun CoroutineScope.sendAnalyticsCreateLink(
analytics: Analytics
analytics: Analytics,
spaceParams: AnalyticSpaceHelperDelegate.Params
) {
sendEvent(
analytics = analytics,
eventName = EventsDictionary.objectCreateLink
eventName = objectCreateLink,
props = Props(
buildMap {
put(EventsPropertiesKey.permissions, spaceParams.permission)
put(EventsPropertiesKey.spaceType, spaceParams.spaceType)
}
)
)
}

View file

@ -59,6 +59,7 @@ import com.anytypeio.anytype.domain.widgets.SetWidgetActiveView
import com.anytypeio.anytype.domain.widgets.UpdateWidget
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.BuildConfig
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.sendAddWidgetEvent
import com.anytypeio.anytype.presentation.extension.sendAnalyticsObjectCreateEvent
import com.anytypeio.anytype.presentation.extension.sendAnalyticsObjectTypeSelectOrChangeEvent
@ -165,14 +166,16 @@ class HomeScreenViewModel(
private val searchObjects: SearchObjects,
private val getPinnedObjectTypes: GetPinnedObjectTypes,
private val userPermissionProvider: UserPermissionProvider,
private val deepLinkToObjectDelegate: DeepLinkToObjectDelegate
private val deepLinkToObjectDelegate: DeepLinkToObjectDelegate,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : NavigationViewModel<HomeScreenViewModel.Navigation>(),
Reducer<ObjectView, Payload>,
WidgetActiveViewStateHolder by widgetActiveViewStateHolder,
WidgetSessionStateHolder by widgetSessionStateHolder,
CollapsedWidgetStateHolder by collapsedWidgetStateHolder,
DeepLinkToObjectDelegate by deepLinkToObjectDelegate,
Unsubscriber by unsubscriber {
Unsubscriber by unsubscriber,
AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
private val jobs = mutableListOf<Job>()
private val mutex = Mutex()
@ -1217,12 +1220,14 @@ class HomeScreenViewModel(
createObject.stream(params).collect { createObjectResponse ->
createObjectResponse.fold(
onSuccess = { result ->
val spaceParams = provideParams(spaceManager.get())
sendAnalyticsObjectCreateEvent(
analytics = analytics,
route = EventsDictionary.Routes.navigation,
startTime = startTime,
view = EventsDictionary.View.viewHome,
objType = objType ?: storeOfObjectTypes.getByKey(result.typeKey.key),
spaceParams = spaceParams
)
if (objType != null) {
sendAnalyticsObjectTypeSelectOrChangeEvent(
@ -1230,7 +1235,8 @@ class HomeScreenViewModel(
startTime = startTime,
sourceObject = objType.sourceObject,
containsFlagType = true,
route = EventsDictionary.Routes.longTap
route = EventsDictionary.Routes.longTap,
spaceParams = spaceParams
)
}
proceedWithOpeningObject(result.obj)
@ -1581,7 +1587,8 @@ class HomeScreenViewModel(
private val searchObjects: SearchObjects,
private val getPinnedObjectTypes: GetPinnedObjectTypes,
private val userPermissionProvider: UserPermissionProvider,
private val deepLinkToObjectDelegate: DeepLinkToObjectDelegate
private val deepLinkToObjectDelegate: DeepLinkToObjectDelegate,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T = HomeScreenViewModel(
@ -1620,7 +1627,8 @@ class HomeScreenViewModel(
searchObjects = searchObjects,
getPinnedObjectTypes = getPinnedObjectTypes,
userPermissionProvider = userPermissionProvider,
deepLinkToObjectDelegate = deepLinkToObjectDelegate
deepLinkToObjectDelegate = deepLinkToObjectDelegate,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}

View file

@ -28,6 +28,7 @@ import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
import com.anytypeio.anytype.domain.workspace.RemoveObjectsFromWorkspace
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.BuildConfig
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.sendAnalyticsObjectCreateEvent
import com.anytypeio.anytype.presentation.home.HomeScreenViewModel.Companion.HOME_SCREEN_PROFILE_OBJECT_SUBSCRIPTION
import com.anytypeio.anytype.presentation.home.OpenObjectNavigation
@ -72,8 +73,9 @@ class LibraryViewModel(
private val storelessSubscriptionContainer: StorelessSubscriptionContainer,
private val appCoroutineDispatchers: AppCoroutineDispatchers,
private val urlBuilder: UrlBuilder,
private val storeOfObjectTypes: StoreOfObjectTypes
) : NavigationViewModel<LibraryViewModel.Navigation>() {
private val storeOfObjectTypes: StoreOfObjectTypes,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : NavigationViewModel<LibraryViewModel.Navigation>(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
val icon = MutableStateFlow<ProfileIconView>(ProfileIconView.Loading)
@ -211,7 +213,8 @@ class LibraryViewModel(
route = EventsDictionary.Routes.objCreateLibrary,
startTime = startTime,
objType = objType ?: storeOfObjectTypes.getByKey(result.typeKey.key),
view = EventsDictionary.View.viewHome
view = EventsDictionary.View.viewHome,
spaceParams = provideParams(spaceManager.get())
)
},
onFailure = { e -> Timber.e(e, "Error while creating a new object") }
@ -497,7 +500,8 @@ class LibraryViewModel(
private val storelessSubscriptionContainer: StorelessSubscriptionContainer,
private val appCoroutineDispatchers: AppCoroutineDispatchers,
private val urlBuilder: UrlBuilder,
private val storeOfObjectTypes: StoreOfObjectTypes
private val storeOfObjectTypes: StoreOfObjectTypes,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -517,7 +521,8 @@ class LibraryViewModel(
storelessSubscriptionContainer = storelessSubscriptionContainer,
appCoroutineDispatchers = appCoroutineDispatchers,
urlBuilder = urlBuilder,
storeOfObjectTypes = storeOfObjectTypes
storeOfObjectTypes = storeOfObjectTypes,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -11,6 +11,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.domain.workspace.getSpaceWithTechSpace
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
@ -24,13 +25,15 @@ class BackLinkOrAddToObjectViewModel(
searchObjects: SearchObjects,
getObjectTypes: GetObjectTypes,
private val analytics: Analytics,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ObjectSearchViewModel(
urlBuilder = urlBuilder,
getObjectTypes = getObjectTypes,
searchObjects = searchObjects,
analytics = analytics,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) {
private val _commands = MutableSharedFlow<Command>(replay = 0)

View file

@ -8,12 +8,14 @@ import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.ext.rangeIntersection
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_utils.tools.UrlValidator
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.domain.workspace.getSpaceWithTechSpace
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.Editor
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSearchResultEvent
import com.anytypeio.anytype.presentation.objects.ObjectIcon
@ -39,8 +41,9 @@ class LinkToObjectOrWebViewModel(
private val analytics: Analytics,
private val stores: Editor.Storage,
private val urlValidator: UrlValidator,
private val spaceManager: SpaceManager
) : ViewModel() {
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
val viewState = MutableStateFlow<ViewState>(ViewState.Init)
val commands = MutableSharedFlow<Command>(replay = 0)
@ -213,11 +216,14 @@ class LinkToObjectOrWebViewModel(
}
private fun onObjectClickEvent(position: Int) {
viewModelScope.sendAnalyticsSearchResultEvent(
analytics = analytics,
pos = position + 1,
length = userInput.value.length
)
viewModelScope.launch {
sendAnalyticsSearchResultEvent(
analytics = analytics,
pos = position + 1,
length = userInput.value.length,
spaceParams = provideParams(spaceManager.get())
)
}
}
suspend fun getSearchObjectsParams(ignore: Id) = SearchObjects.Params(

View file

@ -11,6 +11,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.domain.workspace.getSpaceWithTechSpace
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
import com.anytypeio.anytype.presentation.objects.SupportedLayouts
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
@ -23,13 +24,15 @@ class LinkToObjectViewModel(
searchObjects: SearchObjects,
getObjectTypes: GetObjectTypes,
analytics: Analytics,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ObjectSearchViewModel(
urlBuilder = urlBuilder,
getObjectTypes = getObjectTypes,
searchObjects = searchObjects,
analytics = analytics,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) {
val commands = MutableSharedFlow<Command>(replay = 0)

View file

@ -9,6 +9,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.Editor
import javax.inject.Inject
@ -17,7 +18,8 @@ class LinkToObjectViewModelFactory(
private val getObjectTypes: GetObjectTypes,
private val searchObjects: SearchObjects,
private val analytics: Analytics,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -27,7 +29,8 @@ class LinkToObjectViewModelFactory(
getObjectTypes = getObjectTypes,
searchObjects = searchObjects,
analytics = analytics,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}
@ -39,7 +42,8 @@ class LinkToObjectOrWebViewModelFactory(
private val analytics: Analytics,
private val stores: Editor.Storage,
private val urlValidator: UrlValidator,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -51,7 +55,8 @@ class LinkToObjectOrWebViewModelFactory(
analytics = analytics,
stores = stores,
urlValidator = urlValidator,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}
@ -61,7 +66,8 @@ class BackLinkOrAddToObjectViewModelFactory @Inject constructor(
private val getObjectTypes: GetObjectTypes,
private val searchObjects: SearchObjects,
private val analytics: Analytics,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -71,7 +77,8 @@ class BackLinkOrAddToObjectViewModelFactory @Inject constructor(
getObjectTypes = getObjectTypes,
searchObjects = searchObjects,
analytics = analytics,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.core_models.DVFilterCondition
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.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_utils.ui.TextInputDialogBottomBehaviorApplier
import com.anytypeio.anytype.domain.base.Resultat
import com.anytypeio.anytype.domain.base.fold
@ -17,6 +18,7 @@ import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSearchResultEvent
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
import com.anytypeio.anytype.presentation.objects.SupportedLayouts
@ -40,8 +42,10 @@ class MoveToViewModel(
private val searchObjects: SearchObjects,
private val getObjectTypes: GetObjectTypes,
private val analytics: Analytics,
private val spaceManager: SpaceManager
) : ViewModel(), TextInputDialogBottomBehaviorApplier.OnDialogCancelListener {
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModel(), TextInputDialogBottomBehaviorApplier.OnDialogCancelListener,
AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
private val _viewState: MutableStateFlow<MoveToView> = MutableStateFlow(MoveToView.Init)
val viewState: StateFlow<MoveToView> get() = _viewState
@ -112,11 +116,14 @@ class MoveToViewModel(
if (value is MoveToView.Success) {
val index = value.objects.indexOfFirst { it.id == id }
if (index != -1) {
viewModelScope.sendAnalyticsSearchResultEvent(
analytics = analytics,
pos = index + 1,
length = userInput.value.length
)
viewModelScope.launch {
sendAnalyticsSearchResultEvent(
analytics = analytics,
pos = index + 1,
length = userInput.value.length,
spaceParams = provideParams(spaceManager.get())
)
}
}
}
}

View file

@ -7,13 +7,15 @@ import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
class MoveToViewModelFactory(
private val urlBuilder: UrlBuilder,
private val getObjectTypes: GetObjectTypes,
private val searchObjects: SearchObjects,
private val analytics: Analytics,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -23,7 +25,8 @@ class MoveToViewModelFactory(
getObjectTypes = getObjectTypes,
searchObjects = searchObjects,
analytics = analytics,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -25,14 +25,12 @@ import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
import com.anytypeio.anytype.domain.launch.GetDefaultObjectType
import com.anytypeio.anytype.domain.launch.SetDefaultObjectType
import com.anytypeio.anytype.domain.misc.AppActionManager
import com.anytypeio.anytype.domain.objects.CreateBookmarkObject
import com.anytypeio.anytype.domain.objects.CreatePrefilledNote
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.spaces.AddObjectToSpace
import com.anytypeio.anytype.domain.types.GetPinnedObjectTypes
import com.anytypeio.anytype.domain.types.SetPinnedObjectTypes
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.extension.sendAnalyticsObjectCreateEvent
import com.anytypeio.anytype.presentation.home.OpenObjectNavigation
@ -48,9 +46,8 @@ import kotlinx.coroutines.launch
import timber.log.Timber
class SelectObjectTypeViewModel(
private val params: Params,
private val vmParams: Params,
private val getObjectTypes: GetObjectTypes,
private val spaceManager: SpaceManager,
private val addObjectToSpace: AddObjectToSpace,
private val setPinnedObjectTypes: SetPinnedObjectTypes,
private val getPinnedObjectTypes: GetPinnedObjectTypes,
@ -58,10 +55,9 @@ class SelectObjectTypeViewModel(
private val setDefaultObjectType: SetDefaultObjectType,
private val createBookmarkObject: CreateBookmarkObject,
private val createPrefilledNote: CreatePrefilledNote,
private val appActionManager: AppActionManager,
private val analytics: Analytics,
private val storeOfObjectTypes: StoreOfObjectTypes
) : BaseViewModel() {
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : BaseViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
val viewState = MutableStateFlow<SelectTypeViewState>(SelectTypeViewState.Loading)
val clipboardToolbarViewState = MutableStateFlow<ClipboardToolbarViewState>(ClipboardToolbarViewState.Hidden)
@ -78,7 +74,7 @@ class SelectObjectTypeViewModel(
init {
viewModelScope.launch {
getPinnedObjectTypes.flow(
GetPinnedObjectTypes.Params(params.space)
GetPinnedObjectTypes.Params(vmParams.space)
).collect { pinned.value = it }
}
viewModelScope.launch {
@ -88,13 +84,13 @@ class SelectObjectTypeViewModel(
sorts = ObjectSearchConstants.defaultObjectTypeSearchSorts(),
filters = ObjectSearchConstants.filterTypes(
spaces = buildList {
add(params.space.id)
add(vmParams.space.id)
if (query.isNotEmpty()) {
add(Marketplace.MARKETPLACE_SPACE_ID)
}
},
recommendedLayouts = SupportedLayouts.createObjectLayouts,
excludedTypeKeys = params.excludedTypeKeys
excludedTypeKeys = vmParams.excludedTypeKeys
),
keys = ObjectSearchConstants.defaultKeysObjectType,
query = query
@ -118,7 +114,7 @@ class SelectObjectTypeViewModel(
.sortedBy { obj -> pinnedObjectTypesIds.indexOf(obj.id) }
val (allUserTypes, allLibraryTypes) = allTypes.partition { type ->
type.getValue<Id>(Relations.SPACE_ID) == params.space.id
type.getValue<Id>(Relations.SPACE_ID) == vmParams.space.id
}
val filteredLibraryTypes = allLibraryTypes.filter { type ->
allUserTypes.none { it.uniqueKey == type.uniqueKey }
@ -288,7 +284,7 @@ class SelectObjectTypeViewModel(
viewModelScope.launch {
setPinnedObjectTypes.async(
SetPinnedObjectTypes.Params(
space = params.space,
space = vmParams.space,
types = pinned
)
).fold(
@ -306,7 +302,7 @@ class SelectObjectTypeViewModel(
viewModelScope.launch {
setDefaultObjectType.async(
SetDefaultObjectType.Params(
space = params.space,
space = vmParams.space,
type = TypeId(typeView.id)
)
).fold(
@ -325,7 +321,7 @@ class SelectObjectTypeViewModel(
if (typeView.isFromLibrary) {
val params = AddObjectToSpace.Params(
obj = typeView.id,
space = params.space.id
space = vmParams.space.id
)
addObjectToSpace.async(params = params).fold(
onSuccess = { result ->
@ -380,7 +376,7 @@ class SelectObjectTypeViewModel(
val startTime = System.currentTimeMillis()
createBookmarkObject(
CreateBookmarkObject.Params(
space = params.space.id,
space = vmParams.space.id,
url = url,
details = mapOf(
Relations.ORIGIN to ObjectOrigin.CLIPBOARD.code.toDouble()
@ -398,7 +394,7 @@ class SelectObjectTypeViewModel(
navigation.emit(
OpenObjectNavigation.OpenEditor(
target = obj,
space = params.space.id
space = vmParams.space.id
)
)
},
@ -422,7 +418,7 @@ class SelectObjectTypeViewModel(
createPrefilledNote.async(
CreatePrefilledNote.Params(
text = text,
space = params.space.id,
space = vmParams.space.id,
details = mapOf(
Relations.ORIGIN to ObjectOrigin.CLIPBOARD.code.toDouble()
),
@ -434,12 +430,13 @@ class SelectObjectTypeViewModel(
analytics = analytics,
objType = defaultObjectType?.key ?: ObjectTypeUniqueKeys.NOTE,
route = EventsDictionary.Routes.sharingExtension,
startTime = startTime
startTime = startTime,
spaceParams = provideParams(vmParams.space.id)
)
navigation.emit(
OpenObjectNavigation.OpenEditor(
target = obj,
space = params.space.id
space = vmParams.space.id
)
)
},
@ -454,7 +451,6 @@ class SelectObjectTypeViewModel(
class Factory @Inject constructor(
private val params: Params,
private val getObjectTypes: GetObjectTypes,
private val spaceManager: SpaceManager,
private val addObjectToSpace: AddObjectToSpace,
private val setPinnedObjectTypes: SetPinnedObjectTypes,
private val getPinnedObjectTypes: GetPinnedObjectTypes,
@ -462,17 +458,15 @@ class SelectObjectTypeViewModel(
private val setDefaultObjectType: SetDefaultObjectType,
private val createBookmarkObject: CreateBookmarkObject,
private val createPrefilledNote: CreatePrefilledNote,
private val appActionManager: AppActionManager,
private val storeOfObjectTypes: StoreOfObjectTypes,
private val analytics: Analytics
private val analytics: Analytics,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(
modelClass: Class<T>
) = SelectObjectTypeViewModel(
params = params,
vmParams = params,
getObjectTypes = getObjectTypes,
spaceManager = spaceManager,
addObjectToSpace = addObjectToSpace,
setPinnedObjectTypes = setPinnedObjectTypes,
getPinnedObjectTypes = getPinnedObjectTypes,
@ -480,9 +474,8 @@ class SelectObjectTypeViewModel(
setDefaultObjectType = setDefaultObjectType,
createBookmarkObject = createBookmarkObject,
createPrefilledNote = createPrefilledNote,
appActionManager = appActionManager,
storeOfObjectTypes = storeOfObjectTypes,
analytics = analytics
analytics = analytics,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}

View file

@ -28,6 +28,7 @@ import com.anytypeio.anytype.domain.page.AddBackLinkToObject
import com.anytypeio.anytype.domain.templates.CreateTemplateFromObject
import com.anytypeio.anytype.domain.widgets.CreateWidget
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.editor.Editor
@ -65,7 +66,8 @@ class ObjectMenuViewModel(
private val setObjectDetails: SetObjectDetails,
private val debugGoroutinesShareDownloader: DebugGoroutinesShareDownloader,
private val spaceManager: SpaceManager,
private val deepLinkResolver: DeepLinkResolver
private val deepLinkResolver: DeepLinkResolver,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ObjectMenuViewModelBase(
setObjectIsArchived = setObjectIsArchived,
addToFavorite = addToFavorite,
@ -80,7 +82,8 @@ class ObjectMenuViewModel(
addObjectToCollection = addObjectToCollection,
debugGoroutinesShareDownloader = debugGoroutinesShareDownloader,
createWidget = createWidget,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) {
private val objectRestrictions = storage.objectRestrictions.current()
@ -347,7 +350,8 @@ class ObjectMenuViewModel(
analytics = analytics,
details = storage.details.current().details,
ctx = ctx,
startTime = startTime
startTime = startTime,
spaceParams = provideParams(space)
)
buildOpenTemplateCommand(
ctx = ctx,
@ -459,7 +463,8 @@ class ObjectMenuViewModel(
private val debugGoroutinesShareDownloader: DebugGoroutinesShareDownloader,
private val createWidget: CreateWidget,
private val spaceManager: SpaceManager,
private val deepLinkResolver: DeepLinkResolver
private val deepLinkResolver: DeepLinkResolver,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return ObjectMenuViewModel(
@ -482,7 +487,8 @@ class ObjectMenuViewModel(
debugGoroutinesShareDownloader = debugGoroutinesShareDownloader,
createWidget = createWidget,
spaceManager = spaceManager,
deepLinkResolver = deepLinkResolver
deepLinkResolver = deepLinkResolver,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -22,6 +22,7 @@ import com.anytypeio.anytype.domain.objects.SetObjectIsArchived
import com.anytypeio.anytype.domain.page.AddBackLinkToObject
import com.anytypeio.anytype.domain.widgets.CreateWidget
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.common.Delegator
@ -58,8 +59,9 @@ abstract class ObjectMenuViewModelBase(
private val addObjectToCollection: AddObjectToCollection,
private val debugGoroutinesShareDownloader: DebugGoroutinesShareDownloader,
private val createWidget: CreateWidget,
private val spaceManager: SpaceManager
) : BaseViewModel() {
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : BaseViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
protected val jobs = mutableListOf<Job>()
val isDismissed = MutableStateFlow(false)
@ -285,7 +287,8 @@ abstract class ObjectMenuViewModelBase(
onSuccess = { obj ->
sendAnalyticsBackLinkAddEvent(
analytics = analytics,
startTime = startTime
startTime = startTime,
spaceParams = provideParams(space)
)
commands.emit(
Command.OpenSnackbar(
@ -350,7 +353,8 @@ abstract class ObjectMenuViewModelBase(
analytics = analytics,
startTime = startTime,
details = details,
ctx = ctx
ctx = ctx,
spaceParams = provideParams(space)
)
}
)

View file

@ -19,6 +19,7 @@ import com.anytypeio.anytype.domain.objects.SetObjectIsArchived
import com.anytypeio.anytype.domain.page.AddBackLinkToObject
import com.anytypeio.anytype.domain.widgets.CreateWidget
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.objects.ObjectAction
@ -46,7 +47,8 @@ class ObjectSetMenuViewModel(
private val analytics: Analytics,
private val addObjectToCollection: AddObjectToCollection,
private val debugGoroutinesShareDownloader: DebugGoroutinesShareDownloader,
private val deepLinkResolver: DeepLinkResolver
private val deepLinkResolver: DeepLinkResolver,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ObjectMenuViewModelBase(
setObjectIsArchived = setObjectIsArchived,
addToFavorite = addToFavorite,
@ -61,7 +63,8 @@ class ObjectSetMenuViewModel(
addObjectToCollection = addObjectToCollection,
debugGoroutinesShareDownloader = debugGoroutinesShareDownloader,
createWidget = createWidget,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) {
@Suppress("UNCHECKED_CAST")
@ -81,7 +84,8 @@ class ObjectSetMenuViewModel(
private val debugGoroutinesShareDownloader: DebugGoroutinesShareDownloader,
private val createWidget: CreateWidget,
private val spaceManager: SpaceManager,
private val deepLinkResolver: DeepLinkResolver
private val deepLinkResolver: DeepLinkResolver,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return ObjectSetMenuViewModel(
@ -100,7 +104,8 @@ class ObjectSetMenuViewModel(
debugGoroutinesShareDownloader = debugGoroutinesShareDownloader,
createWidget = createWidget,
spaceManager = spaceManager,
deepLinkResolver = deepLinkResolver
deepLinkResolver = deepLinkResolver,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.dataview.interactor.AddRelationToDataView
@ -16,6 +17,7 @@ import com.anytypeio.anytype.domain.dataview.interactor.UpdateDataViewViewer
import com.anytypeio.anytype.domain.relations.GetRelations
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.getPropName
import com.anytypeio.anytype.presentation.extension.sendAnalyticsAddRelationEvent
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
@ -37,7 +39,8 @@ class RelationAddToDataViewViewModel(
private val analytics: Analytics,
private val addObjectToWorkspace: AddObjectToWorkspace,
private val appCoroutineDispatchers: AppCoroutineDispatchers,
spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : RelationAddViewModelBase(
relationsProvider = relationsProvider,
appCoroutineDispatchers = appCoroutineDispatchers,
@ -73,7 +76,8 @@ class RelationAddToDataViewViewModel(
sendAnalyticsAddRelationEvent(
analytics = analytics,
type = screenType,
format = format.getPropName()
format = format.getPropName(),
spaceParams = analyticSpaceHelperDelegate.provideParams(spaceManager.get())
)
},
failure = {
@ -114,7 +118,8 @@ class RelationAddToDataViewViewModel(
private val appCoroutineDispatchers: AppCoroutineDispatchers,
private val getRelations: GetRelations,
private val addObjectToWorkspace: AddObjectToWorkspace,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -128,7 +133,8 @@ class RelationAddToDataViewViewModel(
appCoroutineDispatchers = appCoroutineDispatchers,
getRelations = getRelations,
addObjectToWorkspace = addObjectToWorkspace,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -8,12 +8,14 @@ import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.GetRelations
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.getPropName
import com.anytypeio.anytype.presentation.extension.sendAnalyticsAddRelationEvent
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
@ -27,18 +29,19 @@ class RelationAddToObjectViewModel(
private val addRelationToObject: AddRelationToObject,
private val dispatcher: Dispatcher<Payload>,
private val analytics: Analytics,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
val storeOfRelations: StoreOfRelations,
appCoroutineDispatchers: AppCoroutineDispatchers,
getRelations: GetRelations,
addObjectToWorkspace: AddObjectToWorkspace,
spaceManager: SpaceManager
private val spaceManager: SpaceManager
) : RelationAddViewModelBase(
relationsProvider = relationsProvider,
appCoroutineDispatchers = appCoroutineDispatchers,
getRelations = getRelations,
addObjectToWorkspace = addObjectToWorkspace,
spaceManager = spaceManager
) {
), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
val commands = MutableSharedFlow<Command>(replay = 0)
@ -61,7 +64,8 @@ class RelationAddToObjectViewModel(
sendAnalyticsAddRelationEvent(
analytics = analytics,
type = screenType,
format = format.getPropName()
format = format.getPropName(),
spaceParams = provideParams(spaceManager.get())
)
isDismissed.value = true
}
@ -83,7 +87,8 @@ class RelationAddToObjectViewModel(
private val appCoroutineDispatchers: AppCoroutineDispatchers,
private val getRelations: GetRelations,
private val addObjectToWorkspace: AddObjectToWorkspace,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -96,7 +101,8 @@ class RelationAddToObjectViewModel(
appCoroutineDispatchers = appCoroutineDispatchers,
getRelations = getRelations,
addObjectToWorkspace = addObjectToWorkspace,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -6,12 +6,14 @@ import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.analytics.base.EventsDictionary
import com.anytypeio.anytype.core_models.*
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.dataview.interactor.AddRelationToDataView
import com.anytypeio.anytype.domain.dataview.interactor.UpdateDataViewViewer
import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.CreateRelation
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.extension.sendAnalyticsCreateRelationEvent
import com.anytypeio.anytype.presentation.relations.model.CreateFromScratchState
@ -87,8 +89,10 @@ class RelationCreateFromScratchForObjectViewModel(
private val addRelationToObject: AddRelationToObject,
private val dispatcher: Dispatcher<Payload>,
private val analytics: Analytics,
private val spaceManager: SpaceManager
) : RelationCreateFromScratchBaseViewModel() {
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : RelationCreateFromScratchBaseViewModel(),
AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
override val createFromScratchSession get() = createFromScratchState.state
@ -117,7 +121,8 @@ class RelationCreateFromScratchForObjectViewModel(
sendAnalyticsCreateRelationEvent(
analytics = analytics,
type = EventsDictionary.Type.menu,
format = format.name
format = format.name,
spaceParams = provideParams(spaceManager.get())
)
}
},
@ -152,7 +157,8 @@ class RelationCreateFromScratchForObjectViewModel(
private val addRelationToObject: AddRelationToObject,
private val dispatcher: Dispatcher<Payload>,
private val analytics: Analytics,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -162,7 +168,8 @@ class RelationCreateFromScratchForObjectViewModel(
createFromScratchState = createFromScratchState,
createRelation = createRelation,
addRelationToObject = addRelationToObject,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}
@ -174,8 +181,10 @@ class RelationCreateFromScratchForObjectBlockViewModel(
private val analytics: Analytics,
private val createFromScratchState: StateHolder<CreateFromScratchState>,
private val createRelation: CreateRelation,
private val spaceManager: SpaceManager
) : RelationCreateFromScratchBaseViewModel() {
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : RelationCreateFromScratchBaseViewModel(),
AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
override val createFromScratchSession get() = createFromScratchState.state
@ -207,7 +216,10 @@ class RelationCreateFromScratchForObjectBlockViewModel(
sendAnalyticsCreateRelationEvent(
analytics = analytics,
type = EventsDictionary.Type.block,
format = format.name
format = format.name,
spaceParams = provideParams(
spaceManager.get()
)
)
}
},
@ -242,7 +254,8 @@ class RelationCreateFromScratchForObjectBlockViewModel(
private val analytics: Analytics,
private val createFromScratchState: StateHolder<CreateFromScratchState>,
private val createRelation: CreateRelation,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -252,7 +265,8 @@ class RelationCreateFromScratchForObjectBlockViewModel(
analytics = analytics,
createFromScratchState = createFromScratchState,
createRelation = createRelation,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}
@ -270,8 +284,10 @@ class RelationCreateFromScratchForDataViewViewModel(
private val analytics: Analytics,
private val createFromScratchState: StateHolder<CreateFromScratchState>,
private val createRelation: CreateRelation,
private val spaceManager: SpaceManager
) : RelationCreateFromScratchBaseViewModel() {
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : RelationCreateFromScratchBaseViewModel(),
AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
override val createFromScratchSession: Flow<CreateFromScratchState> get() = createFromScratchState.state
@ -302,7 +318,8 @@ class RelationCreateFromScratchForDataViewViewModel(
sendAnalyticsCreateRelationEvent(
analytics = analytics,
type = EventsDictionary.Type.dataView,
format = format.name
format = format.name,
spaceParams = provideParams(spaceManager.get())
)
}
},
@ -365,7 +382,8 @@ class RelationCreateFromScratchForDataViewViewModel(
private val createRelation: CreateRelation,
private val dispatcher: Dispatcher<Payload>,
private val analytics: Analytics,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -377,7 +395,8 @@ class RelationCreateFromScratchForDataViewViewModel(
analytics = analytics,
createFromScratchState = createFromScratchState,
createRelation = createRelation,
addRelationToDataView = addRelationToDataView
addRelationToDataView = addRelationToDataView,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -12,6 +12,7 @@ import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.domain.workspace.getSpaceWithTechSpace
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.objects.toRelationObjectValueView
import com.anytypeio.anytype.presentation.relations.RelationValueView
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
@ -32,8 +33,9 @@ class AddObjectRelationViewModel(
private val searchObjects: SearchObjects,
private val urlBuilder: UrlBuilder,
private val storeOfObjectTypes: StoreOfObjectTypes,
private val spaceManager: SpaceManager
) : ViewModel() {
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
private val _views = MutableStateFlow<List<RelationValueView.Object>>(listOf())
private val _filter = MutableStateFlow("")
@ -188,7 +190,8 @@ class AddObjectRelationViewModel(
private val searchObjects: SearchObjects,
private val urlBuilder: UrlBuilder,
private val storeOfObjectTypes: StoreOfObjectTypes,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -198,7 +201,8 @@ class AddObjectRelationViewModel(
searchObjects = searchObjects,
urlBuilder = urlBuilder,
storeOfObjectTypes = storeOfObjectTypes,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -7,6 +7,7 @@ import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_utils.common.EventWrapper
import com.anytypeio.anytype.core_utils.ext.cancel
import com.anytypeio.anytype.core_utils.ui.TextInputDialogBottomBehaviorApplier
@ -19,6 +20,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.domain.workspace.getSpaceWithTechSpace
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSearchResultEvent
import com.anytypeio.anytype.presentation.navigation.AppNavigation
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
@ -43,10 +45,12 @@ open class ObjectSearchViewModel(
private val searchObjects: SearchObjects,
private val getObjectTypes: GetObjectTypes,
private val analytics: Analytics,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewStateViewModel<ObjectSearchView>(),
SupportNavigation<EventWrapper<AppNavigation.Command>>,
TextInputDialogBottomBehaviorApplier.OnDialogCancelListener {
TextInputDialogBottomBehaviorApplier.OnDialogCancelListener,
AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
private val jobs = mutableListOf<Job>()
@ -229,11 +233,14 @@ open class ObjectSearchViewModel(
if (value is ObjectSearchView.Success) {
val index = value.objects.indexOfFirst { (it as? DefaultObjectView)?.id == id }
if (index != -1) {
viewModelScope.sendAnalyticsSearchResultEvent(
analytics = analytics,
pos = index + 1,
length = userInput.value.length
)
viewModelScope.launch {
sendAnalyticsSearchResultEvent(
analytics = analytics,
pos = index + 1,
length = userInput.value.length,
spaceParams = provideParams(spaceManager.get())
)
}
}
}
}

View file

@ -7,13 +7,15 @@ import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
class ObjectSearchViewModelFactory(
private val urlBuilder: UrlBuilder,
private val getObjectTypes: GetObjectTypes,
private val searchObjects: SearchObjects,
private val analytics: Analytics,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -23,7 +25,8 @@ class ObjectSearchViewModelFactory(
getObjectTypes = getObjectTypes,
searchObjects = searchObjects,
analytics = analytics,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -61,6 +61,7 @@ import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.domain.workspace.getSpaceWithTechSpace
import com.anytypeio.anytype.presentation.BuildConfig
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
@ -136,7 +137,7 @@ import kotlinx.coroutines.withTimeout
import timber.log.Timber
class ObjectSetViewModel(
private val params: Params,
private val vmParams: Params,
private val permissions: UserPermissionProvider,
private val database: ObjectSetDatabase,
private val openObjectSet: OpenObjectSet,
@ -176,8 +177,12 @@ class ObjectSetViewModel(
private val storelessSubscriptionContainer: StorelessSubscriptionContainer,
private val dispatchers: AppCoroutineDispatchers,
private val getNetworkMode: GetNetworkMode,
private val dateProvider: DateProvider
) : ViewModel(), SupportNavigation<EventWrapper<AppNavigation.Command>>, ViewerDelegate by viewerDelegate {
private val dateProvider: DateProvider,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModel(), SupportNavigation<EventWrapper<AppNavigation.Command>>,
ViewerDelegate by viewerDelegate,
AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate
{
val icon = MutableStateFlow<ProfileIconView>(ProfileIconView.Loading)
@ -248,12 +253,12 @@ class ObjectSetViewModel(
}
.collectLatest { (state, permission) ->
featured.value = state.featuredRelations(
ctx = params.ctx,
ctx = vmParams.ctx,
urlBuilder = urlBuilder,
relations = storeOfRelations.getAll()
)
_header.value = state.header(
ctx = params.ctx,
ctx = vmParams.ctx,
urlBuilder = urlBuilder,
coverImageHashProvider = coverImageHashProvider,
isReadOnlyMode = permission == SpaceMemberPermissions.NO_PERMISSIONS || permission == SpaceMemberPermissions.READER
@ -294,7 +299,7 @@ class ObjectSetViewModel(
.distinctUntilChanged()
.map {
UpdateText.Params(
context = params.ctx,
context = vmParams.ctx,
target = it.target,
text = it.text,
marks = emptyList()
@ -380,7 +385,7 @@ class ObjectSetViewModel(
private fun proceedWIthObservingPermissions() {
viewModelScope.launch {
permissions
.observe(params.space)
.observe(vmParams.space)
.collect {
permission.value = it
}
@ -389,7 +394,7 @@ class ObjectSetViewModel(
private fun proceedWithObservingProfileIcon() {
viewModelScope.launch {
val config = spaceManager.getConfig(params.space)
val config = spaceManager.getConfig(vmParams.space)
if (config != null) {
storelessSubscriptionContainer.subscribe(
StoreSearchByIdsParams(
@ -422,7 +427,7 @@ class ObjectSetViewModel(
downloadUnsplashImage(
DownloadUnsplashImage.Params(
picture = action.img,
space = params.space
space = vmParams.space
)
).process(
failure = {
@ -467,7 +472,7 @@ class ObjectSetViewModel(
.build(InterceptThreadStatus.Params(ctx))
.collect {
val statusView = it.toView(
networkId = spaceManager.getConfig(params.space)?.network,
networkId = spaceManager.getConfig(vmParams.space)?.network,
networkMode = networkMode
)
status.value = statusView
@ -495,12 +500,12 @@ class ObjectSetViewModel(
Timber.d("subscribeToObjectState, NEW COLLECTION STATE")
if (query.state.isInitialized) {
dataViewSubscription.startObjectCollectionSubscription(
collection = params.ctx,
collection = vmParams.ctx,
state = query.state,
currentViewerId = query.currentViewerId,
offset = query.offset,
context = params.ctx,
spaces = spaceManager.getSpaceWithTechSpace(space = params.space.id),
context = vmParams.ctx,
spaces = spaceManager.getSpaceWithTechSpace(space = vmParams.space.id),
dataViewRelationLinks = query.state.dataViewContent.relationLinks
)
} else {
@ -516,7 +521,7 @@ class ObjectSetViewModel(
currentViewerId = query.currentViewerId,
offset = query.offset,
context = context,
spaces = spaceManager.getSpaceWithTechSpace(params.space.id),
spaces = spaceManager.getSpaceWithTechSpace(vmParams.space.id),
dataViewRelationLinks = query.state.dataViewContent.relationLinks
)
} else {
@ -551,7 +556,7 @@ class ObjectSetViewModel(
openObjectSet(
OpenObjectSet.Params(
obj = ctx,
space = params.space
space = vmParams.space
)
).process(
success = { result ->
@ -578,7 +583,8 @@ class ObjectSetViewModel(
analytics = analytics,
event = ObjectStateAnalyticsEvent.OPEN_OBJECT,
startTime = startTime,
currentViewId = session.currentViewerId.value
currentViewId = session.currentViewerId.value,
spaceParams = provideParams(vmParams.space.id)
)
}
}
@ -1219,8 +1225,8 @@ class ObjectSetViewModel(
if (type.key == ObjectTypeIds.BOOKMARK) {
dispatch(
ObjectSetCommand.Modal.CreateBookmark(
ctx = params.ctx,
space = params.space.id
ctx = vmParams.ctx,
space = vmParams.space.id
)
)
} else {
@ -1356,8 +1362,8 @@ class ObjectSetViewModel(
Timber.d("onCoverClicked, ")
dispatch(
ObjectSetCommand.Modal.OpenCoverActionMenu(
ctx = params.ctx,
space = params.space.id
ctx = vmParams.ctx,
space = vmParams.space.id
)
)
}
@ -1465,7 +1471,7 @@ class ObjectSetViewModel(
isCustomizeViewPanelVisible.value = false
val event = AppNavigation.Command.OpenModalTemplateSelect(
template = target,
space = params.space.id,
space = vmParams.space.id,
templateTypeId = targetTypeId,
templateTypeKey = targetTypeKey
)
@ -1633,7 +1639,8 @@ class ObjectSetViewModel(
route = EventsDictionary.Routes.navigation,
startTime = startTime,
view = EventsDictionary.View.viewNavbar,
objType = objType ?: storeOfObjectTypes.getByKey(result.typeKey.key)
objType = objType ?: storeOfObjectTypes.getByKey(result.typeKey.key),
spaceParams = provideParams(vmParams.space.id)
)
},
onFailure = { e ->
@ -1652,7 +1659,8 @@ class ObjectSetViewModel(
analytics = analytics,
event = ObjectStateAnalyticsEvent.OBJECT_CREATE,
startTime = startTime,
type = objType?.sourceObject ?: OBJ_TYPE_CUSTOM
type = objType?.sourceObject ?: OBJ_TYPE_CUSTOM,
spaceParams = provideParams(vmParams.space.id)
)
}
}
@ -1789,7 +1797,7 @@ class ObjectSetViewModel(
ctx = context,
objectId = context,
relationKey = relation.key,
space = params.space.id
space = vmParams.space.id
)
)
}
@ -1841,7 +1849,8 @@ class ObjectSetViewModel(
analytics = analytics,
event = ObjectStateAnalyticsEvent.SELECT_QUERY,
type = query,
startTime = startTime
startTime = startTime,
spaceParams = provideParams(vmParams.space.id)
)
defaultPayloadConsumer(payload)
},
@ -1862,7 +1871,8 @@ class ObjectSetViewModel(
state = stateReducer.state.value,
analytics = analytics,
event = ObjectStateAnalyticsEvent.TURN_INTO_COLLECTION,
startTime = startTime
startTime = startTime,
spaceParams = provideParams(vmParams.space.id)
)
}
)
@ -2012,7 +2022,8 @@ class ObjectSetViewModel(
state = stateReducer.state.value,
analytics = analytics,
event = event,
type = type
type = type,
spaceParams = provideParams(vmParams.space.id)
)
}
}
@ -2028,7 +2039,7 @@ class ObjectSetViewModel(
.flatMapLatest { selectedType ->
templatesContainer.subscribeToTemplates(
type = selectedType.id,
space = params.space,
space = vmParams.space,
subscription = "$context$SUBSCRIPTION_TEMPLATES_ID"
)
}.map { templates ->
@ -2111,7 +2122,7 @@ class ObjectSetViewModel(
private suspend fun fetchAndProcessObjectTypes(selectedType: Id, widgetState: TypeTemplatesWidgetUI.Data) {
val filters = ObjectSearchConstants.filterTypes(
spaces = listOf(params.space.id),
spaces = listOf(vmParams.space.id),
recommendedLayouts = SupportedLayouts.createObjectLayouts
)
val params = GetObjectTypes.Params(
@ -2215,7 +2226,8 @@ class ObjectSetViewModel(
state = stateReducer.state.value,
analytics = analytics,
event = ObjectStateAnalyticsEvent.CREATE_TEMPLATE,
type = storeOfObjectTypes.get(targetTypeId)?.sourceObject
type = storeOfObjectTypes.get(targetTypeId)?.sourceObject,
spaceParams = provideParams(vmParams.space.id)
)
proceedWithOpeningTemplate(
target = id,
@ -2327,7 +2339,8 @@ class ObjectSetViewModel(
state = stateReducer.state.value,
analytics = analytics,
event = ObjectStateAnalyticsEvent.DUPLICATE_TEMPLATE,
type = template.targetTypeId.id
type = template.targetTypeId.id,
spaceParams = provideParams(vmParams.space.id)
)
Timber.d("Successfully duplicated templates: $ids")
},
@ -2354,7 +2367,8 @@ class ObjectSetViewModel(
state = stateReducer.state.value,
analytics = analytics,
event = ObjectStateAnalyticsEvent.DELETE_TEMPLATE,
type = template.targetTypeKey.key
type = template.targetTypeKey.key,
spaceParams = provideParams(vmParams.space.id)
)
Timber.d("Successfully archived templates: $ids")
},
@ -2383,7 +2397,8 @@ class ObjectSetViewModel(
state = stateReducer.state.value,
analytics = analytics,
event = ObjectStateAnalyticsEvent.EDIT_TEMPLATE,
type = template.targetTypeKey.key
type = template.targetTypeKey.key,
spaceParams = provideParams(vmParams.space.id)
)
}
}
@ -2422,7 +2437,8 @@ class ObjectSetViewModel(
state = state,
analytics = analytics,
event = ObjectStateAnalyticsEvent.REMOVE_VIEW,
startTime = startTime
startTime = startTime,
spaceParams = provideParams(vmParams.space.id)
)
}
)
@ -2455,7 +2471,8 @@ class ObjectSetViewModel(
analytics = analytics,
event = ObjectStateAnalyticsEvent.REPOSITION_VIEW,
startTime = startTime,
type = type.formattedName
type = type.formattedName,
spaceParams = provideParams(vmParams.space.id)
)
}
)
@ -2473,7 +2490,8 @@ class ObjectSetViewModel(
analytics = analytics,
event = ObjectStateAnalyticsEvent.SWITCH_VIEW,
startTime = startTime,
type = action.type.formattedName
type = action.type.formattedName,
spaceParams = provideParams(vmParams.space.id)
)
}
))
@ -2502,7 +2520,8 @@ class ObjectSetViewModel(
analytics = analytics,
event = ObjectStateAnalyticsEvent.ADD_VIEW,
startTime = startTime,
type = newView.type.formattedName
type = newView.type.formattedName,
spaceParams = provideParams(vmParams.space.id)
)
widgetViewerId.value = newViewId
showViewerEditWidgetForNewView()
@ -2610,7 +2629,8 @@ class ObjectSetViewModel(
state = state,
analytics = analytics,
event = ObjectStateAnalyticsEvent.REMOVE_VIEW,
startTime = startTime
startTime = startTime,
spaceParams = provideParams(vmParams.space.id)
)
}
)
@ -2633,7 +2653,8 @@ class ObjectSetViewModel(
analytics = analytics,
event = ObjectStateAnalyticsEvent.DUPLICATE_VIEW,
startTime = startTime,
type = viewer.type.formattedName
type = viewer.type.formattedName,
spaceParams = provideParams(vmParams.space.id)
)
}
)
@ -2783,7 +2804,8 @@ class ObjectSetViewModel(
analytics = analytics,
event = ObjectStateAnalyticsEvent.CHANGE_VIEW_TYPE,
startTime = startTime,
type = action.type.formattedName
type = action.type.formattedName,
spaceParams = provideParams(vmParams.space.id)
)
}
},

View file

@ -33,6 +33,7 @@ import com.anytypeio.anytype.domain.status.InterceptThreadStatus
import com.anytypeio.anytype.domain.templates.CreateTemplate
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
@ -83,12 +84,13 @@ class ObjectSetViewModelFactory(
private val storelessSubscriptionContainer: StorelessSubscriptionContainer,
private val dispatchers: AppCoroutineDispatchers,
private val getNetworkMode: GetNetworkMode,
private val dateProvider: DateProvider
private val dateProvider: DateProvider,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return ObjectSetViewModel(
params = params,
vmParams = params,
permissions = permissions,
openObjectSet = openObjectSet,
closeBlock = closeBlock,
@ -128,7 +130,8 @@ class ObjectSetViewModelFactory(
dispatchers = dispatchers,
storelessSubscriptionContainer = storelessSubscriptionContainer,
getNetworkMode = getNetworkMode,
dateProvider = dateProvider
dateProvider = dateProvider,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -24,6 +24,7 @@ import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.objects.options.GetOptions
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.ObjectStateAnalyticsEvent
import com.anytypeio.anytype.presentation.extension.checkboxFilterValue
import com.anytypeio.anytype.presentation.extension.hasValue
@ -769,7 +770,8 @@ open class FilterViewModel(
analytics = analytics,
event = ObjectStateAnalyticsEvent.CHANGE_FILTER_VALUE,
startTime = startTime,
condition = updatedFilter.condition
condition = updatedFilter.condition,
spaceParams = AnalyticSpaceHelperDelegate.Params.EMPTY
)
isCompleted.emit(true)
}

View file

@ -31,6 +31,7 @@ import com.anytypeio.anytype.domain.objects.CreateBookmarkObject
import com.anytypeio.anytype.domain.objects.CreatePrefilledNote
import com.anytypeio.anytype.domain.spaces.GetSpaceViews
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.extension.sendAnalyticsObjectCreateEvent
import com.anytypeio.anytype.presentation.home.OpenObjectNavigation
@ -59,8 +60,9 @@ class AddToAnytypeViewModel(
private val analytics: Analytics,
private val uploadFile: UploadFile,
private val fileSharer: FileSharer,
private val permissions: Permissions
) : BaseViewModel() {
private val permissions: Permissions,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : BaseViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
private val selectedSpaceId = MutableStateFlow(NO_VALUE)
@ -205,7 +207,8 @@ class AddToAnytypeViewModel(
analytics = analytics,
objType = MarketplaceObjectTypeIds.NOTE,
route = EventsDictionary.Routes.sharingExtension,
startTime = startTime
startTime = startTime,
spaceParams = provideParams(spaceManager.get())
)
if (targetSpaceId == spaceManager.get()) {
navigation.emit(
@ -254,7 +257,8 @@ class AddToAnytypeViewModel(
analytics = analytics,
objType = MarketplaceObjectTypeIds.BOOKMARK,
route = EventsDictionary.Routes.sharingExtension,
startTime = startTime
startTime = startTime,
spaceParams = provideParams(spaceManager.get())
)
if (targetSpaceId == spaceManager.get()) {
navigation.emit(
@ -301,7 +305,8 @@ class AddToAnytypeViewModel(
analytics = analytics,
objType = MarketplaceObjectTypeIds.NOTE,
route = EventsDictionary.Routes.sharingExtension,
startTime = startTime
startTime = startTime,
spaceParams = provideParams(spaceManager.get())
)
if (targetSpaceId == spaceManager.get()) {
navigation.emit(
@ -378,7 +383,8 @@ class AddToAnytypeViewModel(
private val analytics: Analytics,
private val uploadFile: UploadFile,
private val fileSharer: FileSharer,
private val permissions: Permissions
private val permissions: Permissions,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -392,7 +398,8 @@ class AddToAnytypeViewModel(
analytics = analytics,
uploadFile = uploadFile,
fileSharer = fileSharer,
permissions = permissions
permissions = permissions,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -36,6 +36,7 @@ import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
import com.anytypeio.anytype.domain.spaces.SpaceDeletedStatusWatcher
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.BuildConfig
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.sendAnalyticsObjectCreateEvent
import com.anytypeio.anytype.presentation.objects.SupportedLayouts
import kotlinx.coroutines.flow.MutableSharedFlow
@ -62,8 +63,9 @@ class SplashViewModel(
private val spaceDeletedStatusWatcher: SpaceDeletedStatusWatcher,
private val localeProvider: LocaleProvider,
private val spaceManager: SpaceManager,
private val userPermissionProvider: UserPermissionProvider
) : ViewModel() {
private val userPermissionProvider: UserPermissionProvider,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
val state = MutableStateFlow<ViewState<Any>>(ViewState.Init)
@ -176,6 +178,7 @@ class SplashViewModel(
route = EventsDictionary.Routes.home,
startTime = startTime,
view = EventsDictionary.View.viewHome,
spaceParams = provideParams(spaceManager.get())
)
val target = result.objectId
val space = requireNotNull(result.obj.spaceId)

View file

@ -16,6 +16,7 @@ import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
import com.anytypeio.anytype.domain.spaces.SpaceDeletedStatusWatcher
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import javax.inject.Inject
/**
@ -37,7 +38,8 @@ class SplashViewModelFactory @Inject constructor(
private val spaceDeletedStatusWatcher: SpaceDeletedStatusWatcher,
private val localeProvider: LocaleProvider,
private val spaceManager: SpaceManager,
private val userPermissionProvider: UserPermissionProvider
private val userPermissionProvider: UserPermissionProvider,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -56,6 +58,7 @@ class SplashViewModelFactory @Inject constructor(
spaceDeletedStatusWatcher = spaceDeletedStatusWatcher,
localeProvider = localeProvider,
spaceManager = spaceManager,
userPermissionProvider = userPermissionProvider
userPermissionProvider = userPermissionProvider,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}

View file

@ -5,17 +5,21 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.analytics.base.EventsDictionary.libraryCreateType
import com.anytypeio.anytype.analytics.base.EventsPropertiesKey
import com.anytypeio.anytype.analytics.base.sendEvent
import com.anytypeio.anytype.analytics.props.Props
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_utils.ext.orNull
import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.types.CreateObjectType
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.emojifier.data.EmojiProvider
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.navigation.NavigationViewModel
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import javax.inject.Inject
@ -32,8 +36,10 @@ class CreateObjectTypeViewModel(
private val urlBuilder: UrlBuilder,
private val emojiProvider: EmojiProvider,
private val analytics: Analytics,
private val spaceManager: SpaceManager
) : NavigationViewModel<CreateObjectTypeViewModel.Navigation>() {
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : NavigationViewModel<CreateObjectTypeViewModel.Navigation>(),
AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
private val unicodeIconFlow = MutableStateFlow("")
@ -69,7 +75,17 @@ class CreateObjectTypeViewModel(
)
).fold(
onSuccess = {
viewModelScope.sendEvent(analytics = analytics, eventName = libraryCreateType)
val spaceParams = provideParams(spaceManager.get())
viewModelScope.sendEvent(
analytics = analytics,
eventName = libraryCreateType,
props = Props(
mapOf(
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
)
navigate(Navigation.BackWithCreatedType)
},
onFailure = {
@ -109,7 +125,8 @@ class CreateObjectTypeViewModel(
private val urlBuilder: UrlBuilder,
private val emojiProvider: EmojiProvider,
private val analytics: Analytics,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -118,7 +135,8 @@ class CreateObjectTypeViewModel(
urlBuilder = urlBuilder,
emojiProvider = emojiProvider,
analytics = analytics,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -12,6 +12,7 @@ import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.sendChangeWidgetSourceEvent
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
import com.anytypeio.anytype.presentation.search.ObjectSearchSection
@ -32,13 +33,15 @@ class SelectWidgetSourceViewModel(
private val getObjectTypes: GetObjectTypes,
private val analytics: Analytics,
private val dispatcher: Dispatcher<WidgetDispatchEvent>,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ObjectSearchViewModel(
urlBuilder = urlBuilder,
searchObjects = searchObjects,
getObjectTypes = getObjectTypes,
analytics = analytics,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) {
val isDismissed = MutableStateFlow(false)
@ -247,7 +250,8 @@ class SelectWidgetSourceViewModel(
private val getObjectTypes: GetObjectTypes,
private val analytics: Analytics,
private val dispatcher: Dispatcher<WidgetDispatchEvent>,
private val spaceManager: SpaceManager
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -258,7 +262,8 @@ class SelectWidgetSourceViewModel(
analytics = analytics,
getObjectTypes = getObjectTypes,
dispatcher = dispatcher,
spaceManager = spaceManager
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

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.ext.process
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_utils.ext.cancel
import com.anytypeio.anytype.core_utils.ext.replace
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
@ -41,6 +42,7 @@ import com.anytypeio.anytype.domain.page.CreateObject
import com.anytypeio.anytype.domain.spaces.GetSpaceView
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.domain.workspace.getSpaceWithTechSpace
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.sendAnalyticsObjectCreateEvent
import com.anytypeio.anytype.presentation.extension.sendDeletionWarning
import com.anytypeio.anytype.presentation.extension.sendScreenHomeEvent
@ -105,8 +107,9 @@ class CollectionViewModel(
private val storeOfObjectTypes: StoreOfObjectTypes,
private val spaceManager: SpaceManager,
private val getSpaceView: GetSpaceView,
private val dateTypeNameProvider: DateTypeNameProvider
) : ViewModel(), Reducer<CoreObjectView, Payload> {
private val dateTypeNameProvider: DateTypeNameProvider,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModel(), Reducer<CoreObjectView, Payload>, AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
val payloads: Flow<Payload>
@ -849,7 +852,8 @@ class CollectionViewModel(
route = EventsDictionary.Routes.objCreateHome,
startTime = startTime,
objType = objType ?: storeOfObjectTypes.getByKey(result.typeKey.key),
view = EventsDictionary.View.viewHome
view = EventsDictionary.View.viewHome,
spaceParams = provideParams(spaceManager.get())
)
proceedWithOpeningObject(result.obj)
},
@ -934,7 +938,8 @@ class CollectionViewModel(
private val storeOfObjectTypes: StoreOfObjectTypes,
private val spaceManager: SpaceManager,
private val getSpaceView: GetSpaceView,
private val dateTypeNameProvider: DateTypeNameProvider
private val dateTypeNameProvider: DateTypeNameProvider,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -959,7 +964,8 @@ class CollectionViewModel(
storeOfObjectTypes = storeOfObjectTypes,
spaceManager = spaceManager,
getSpaceView = getSpaceView,
dateTypeNameProvider = dateTypeNameProvider
dateTypeNameProvider = dateTypeNameProvider,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}
}

View file

@ -13,6 +13,7 @@ import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.Relations.ID
import com.anytypeio.anytype.core_models.Relations.LAYOUT
import com.anytypeio.anytype.core_models.StubRelationObject
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.objects.getProperName
import com.anytypeio.anytype.presentation.relations.model.DefaultObjectRelationValueView
@ -52,6 +53,7 @@ class CollectionAddRelationTest : ObjectSetViewModelTestSetup() {
viewModel = givenViewModel()
stubNetworkMode()
stubObservePermissions()
stubAnalyticSpaceHelperDelegate()
}
@After

View file

@ -120,14 +120,16 @@ class CollectionCreateAndAddObjectTest: ObjectSetViewModelTestSetup() {
dispatchers = dispatchers,
getNetworkMode = getNetworkMode,
dateProvider = dateProvider,
params = ObjectSetViewModel.Params(
vmParams = ObjectSetViewModel.Params(
ctx = root,
space = SpaceId(defaultSpace)
),
permissions = permissions
permissions = permissions,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
stubNetworkMode()
stubObservePermissions()
stubAnalyticSpaceHelperDelegate()
}
@After

View file

@ -6,6 +6,7 @@ import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.DVSortType
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.presentation.sets.ObjectSetViewModel
import com.anytypeio.anytype.presentation.sets.main.ObjectSetViewModelTestSetup
import com.anytypeio.anytype.presentation.sets.state.ObjectState
@ -33,6 +34,7 @@ class CollectionDataViewUpdateTest : ObjectSetViewModelTestSetup() {
stubGetDefaultPageType()
stubNetworkMode()
stubObservePermissions()
stubAnalyticSpaceHelperDelegate()
}
@After

View file

@ -5,6 +5,7 @@ import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectTypeIds
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_models.primitives.TypeKey
import com.anytypeio.anytype.domain.base.Resultat
import com.anytypeio.anytype.domain.dataview.interactor.CreateDataViewObject
@ -38,6 +39,7 @@ class ObjectCreateTest : ObjectSetViewModelTestSetup() {
stubNetworkMode()
stubCreateDataViewObject()
stubObservePermissions()
stubAnalyticSpaceHelperDelegate()
}
@After

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectTypeIds
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.StubObject
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_models.primitives.TypeKey
import com.anytypeio.anytype.core_models.restrictions.DataViewRestriction
import com.anytypeio.anytype.core_models.restrictions.DataViewRestrictions
@ -46,6 +47,7 @@ class ObjectStateCollectionViewTest : ObjectSetViewModelTestSetup() {
stubGetDefaultPageType()
stubNetworkMode()
stubObservePermissions()
stubAnalyticSpaceHelperDelegate()
}
@After

View file

@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.ObjectTypeIds
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.StubObject
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.presentation.relations.ObjectSetConfig
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
import com.anytypeio.anytype.presentation.sets.DataViewViewState
@ -44,6 +45,7 @@ class ObjectStateSetViewTest : ObjectSetViewModelTestSetup() {
mockObjectSet = MockSet(context = root, space = defaultSpace)
stubNetworkMode()
stubObservePermissions()
stubAnalyticSpaceHelperDelegate()
}
@After

View file

@ -18,6 +18,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@ -153,6 +154,7 @@ class BlockReadModeTest : EditorViewModelTest() {
stubObserveEvents(flow)
stubOpenPage()
stubUserPermission()
stubAnalyticSpaceHelperDelegate()
givenViewModel()
vm.onStart(id = root, space = defaultSpace)
@ -212,6 +214,7 @@ class BlockReadModeTest : EditorViewModelTest() {
stubObserveEvents(flow)
stubOpenPage()
stubUserPermission()
stubAnalyticSpaceHelperDelegate()
givenViewModel()
vm.onStart(id = root, space = defaultSpace)
@ -247,6 +250,7 @@ class BlockReadModeTest : EditorViewModelTest() {
stubObserveEvents(flow)
stubOpenPage()
stubUserPermission()
stubAnalyticSpaceHelperDelegate()
givenViewModel()
vm.onStart(id = root, space = defaultSpace)
@ -302,17 +306,20 @@ class BlockReadModeTest : EditorViewModelTest() {
}
@Test
fun `should enter edit mode after action menu is closed by action item delete`() {
fun `should enter edit mode after action menu is closed by action item delete`() = runTest {
val paragraphs = blocks
stubObserveEvents(flow)
stubOpenPage()
stubUserPermission()
stubAnalyticSpaceHelperDelegate()
stubUnlinkBlocks(root)
givenViewModel()
vm.onStart(id = root, space = defaultSpace)
coroutineTestRule.advanceTime(100)
coroutineTestRule.advanceUntilIdle()
// TESTING
@ -323,8 +330,12 @@ class BlockReadModeTest : EditorViewModelTest() {
)
)
coroutineTestRule.advanceUntilIdle()
vm.onMultiSelectAction(ActionItemType.Delete)
coroutineTestRule.advanceUntilIdle()
val testObserver = vm.state.test()
val initial = blockViewsEditMode
@ -340,12 +351,13 @@ class BlockReadModeTest : EditorViewModelTest() {
}
@Test
fun `should be in read mode and selected after action item duplicate`() {
fun `should be in read mode and selected after action item duplicate`() = runTest {
val paragraphs = blocks
stubObserveEvents(flow)
stubOpenPage()
stubUserPermission()
stubAnalyticSpaceHelperDelegate()
stubDuplicateBlock(
newBlockId = MockDataFactory.randomUuid(),
root = root

View file

@ -94,10 +94,10 @@ import com.anytypeio.anytype.domain.templates.ApplyTemplate
import com.anytypeio.anytype.domain.templates.GetTemplates
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
import com.anytypeio.anytype.domain.unsplash.UnsplashRepository
import com.anytypeio.anytype.domain.workspace.FileLimitsEventChannel
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.MockBlockFactory
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
@ -134,22 +134,16 @@ import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runBlockingTest
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Assert.assertThrows
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -364,6 +358,9 @@ open class EditorViewModelTest {
@Mock
lateinit var storelessSubscriptionContainer: StorelessSubscriptionContainer
@Mock
lateinit var analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
@Mock
lateinit var permissions: UserPermissionProvider
@ -406,6 +403,7 @@ open class EditorViewModelTest {
private val storeOfObjectTypes: StoreOfObjectTypes = DefaultStoreOfObjectTypes()
val defaultSpace = MockDataFactory.randomString()
val spaceId = SpaceId(defaultSpace)
@Before
fun setup() {
@ -420,6 +418,7 @@ open class EditorViewModelTest {
get()
} doReturn defaultSpace
}
stubAnalyticSpaceHelperDelegate()
stubFileLimitEvents()
stubUpdateBlocksMark()
stubOpenPage(root, emptyList())
@ -455,7 +454,7 @@ open class EditorViewModelTest {
val param = OpenPage.Params(
obj = root,
saveAsLastOpened = true,
space = SpaceId(defaultSpace)
space = spaceId
)
stubInterceptEvents()
@ -1088,6 +1087,7 @@ open class EditorViewModelTest {
stubObserveEvents(events)
stubOpenPage()
stubUserPermission()
stubAnalyticSpaceHelperDelegate()
givenViewModel(builder)
vm.onStart(id = root, space = defaultSpace)
@ -2014,7 +2014,7 @@ open class EditorViewModelTest {
}
}
private fun stubUnlinkBlocks(root: String) {
fun stubUnlinkBlocks(root: String) {
unlinkBlocks.stub {
onBlocking { invoke(any()) } doReturn Either.Right(
Payload(
@ -2233,23 +2233,28 @@ open class EditorViewModelTest {
stubOpenPage(context = root)
stubCreateBlock(root)
stubUnlinkBlocks(root)
stubInterceptThreadStatus()
givenViewModel()
vm.onStart(id = root, space = defaultSpace)
coroutineTestRule.advanceTime(100)
advanceUntilIdle()
vm.onBlockFocusChanged(
id = child,
hasFocus = true
)
advanceUntilIdle()
vm.onEndLineEnterClicked(
id = child,
text = page.last().content<Block.Content.Text>().text,
marks = emptyList()
)
advanceUntilIdle()
verify(createBlock, times(1)).async(
params = eq(
CreateBlock.Params(
@ -3692,7 +3697,7 @@ open class EditorViewModelTest {
async(
OpenPage.Params(
obj = context,
space = SpaceId(defaultSpace),
space = spaceId,
saveAsLastOpened = true
)
)
@ -3916,7 +3921,9 @@ open class EditorViewModelTest {
createTable = createTable,
fillTableRow = fillTableRow,
clearBlockContent = clearBlockContent,
clearBlockStyle = clearBlockStyle
clearBlockStyle = clearBlockStyle,
analyticsSpaceHelperDelegate = analyticSpaceHelperDelegate,
spaceManager = spaceManager,
),
analytics = analytics,
dispatcher = Dispatcher.Default(),
@ -3947,11 +3954,12 @@ open class EditorViewModelTest {
storelessSubscriptionContainer = storelessSubscriptionContainer,
dispatchers = dispatchers,
getNetworkMode = getNetworkMode,
params = EditorViewModel.Params(
vmParams = EditorViewModel.Params(
ctx = root,
space = SpaceId(defaultSpace)
space = spaceId
),
permissions = permissions
permissions = permissions,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
}
@ -4389,7 +4397,7 @@ open class EditorViewModelTest {
}
fun stubUserPermission(
space: SpaceId = SpaceId(defaultSpace),
space: SpaceId = spaceId,
permission: SpaceMemberPermissions = SpaceMemberPermissions.OWNER
) {
permissions.stub {
@ -4398,4 +4406,10 @@ open class EditorViewModelTest {
} doReturn flowOf(permission)
}
}
fun stubAnalyticSpaceHelperDelegate() {
analyticSpaceHelperDelegate.stub {
on { provideParams(defaultSpace) } doReturn AnalyticSpaceHelperDelegate.Params.EMPTY
}
}
}

View file

@ -2,11 +2,13 @@ package com.anytypeio.anytype.presentation.editor.editor
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.anytypeio.anytype.presentation.MockTypicalDocumentFactory
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -21,7 +23,7 @@ class EditorBackButtonTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -31,10 +33,11 @@ class EditorBackButtonTest : EditorPresentationTestSetup() {
stubGetNetworkMode()
stubFileLimitEvents()
stubInterceptEvents()
stubAnalyticSpaceHelperDelegate()
}
@Test
fun `should proceed to the exit when the system back button is pressed`() {
fun `should proceed to the exit when the system back button is pressed`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
@ -44,6 +47,8 @@ class EditorBackButtonTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
// TESTING
val stateBefore = vm.controlPanelViewState.value
@ -53,6 +58,8 @@ class EditorBackButtonTest : EditorPresentationTestSetup() {
vm.onSystemBackPressed(editorHasChildrenScreens = false)
advanceUntilIdle()
val stateBackPressed = vm.controlPanelViewState.value
assertTrue(stateBackPressed?.styleTextToolbar?.isVisible == false)

View file

@ -19,11 +19,13 @@ import com.anytypeio.anytype.core_models.StubRelationObject
import com.anytypeio.anytype.core_models.StubTitle
import com.anytypeio.anytype.core_models.StubToggle
import com.anytypeio.anytype.core_models.ext.content
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.block.interactor.MergeBlocks
import com.anytypeio.anytype.domain.block.interactor.UnlinkBlocks
import com.anytypeio.anytype.domain.block.interactor.UpdateText
import com.anytypeio.anytype.domain.block.interactor.UpdateTextStyle
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.EditorViewModel
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.editor.render.parseThemeBackgroundColor
@ -38,6 +40,8 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.stub
import org.mockito.kotlin.times
import org.mockito.kotlin.verifyBlocking
import org.mockito.kotlin.verifyNoInteractions
@ -1351,6 +1355,7 @@ class EditorBackspaceDeleteTest : EditorPresentationTestSetup() {
stubGetTemplates()
stubUpdateTextStyle()
stubMergeBlocks(root)
stubAnalyticSpaceHelperDelegate()
storeOfRelations.merge(
relations = listOf(relation)

View file

@ -7,9 +7,11 @@ import com.anytypeio.anytype.core_models.ext.content
import com.anytypeio.anytype.domain.base.Either
import com.anytypeio.anytype.domain.block.interactor.UpdateCheckbox
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -28,7 +30,7 @@ class EditorCheckboxTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -37,10 +39,11 @@ class EditorCheckboxTest : EditorPresentationTestSetup() {
stubGetNetworkMode()
stubFileLimitEvents()
stubInterceptEvents()
stubAnalyticSpaceHelperDelegate()
}
@Test
fun `should start updating checkbox as checked when it is clicked`() {
fun `should start updating checkbox as checked when it is clicked`() = runTest {
// SETUP
@ -84,8 +87,12 @@ class EditorCheckboxTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.onCheckboxClicked(view)
advanceUntilIdle()
verifyBlocking(updateCheckbox, times(1)) {
invoke(
eq(
@ -100,7 +107,7 @@ class EditorCheckboxTest : EditorPresentationTestSetup() {
}
@Test
fun `should start updating checkbox as not checked when it is clicked`() {
fun `should start updating checkbox as not checked when it is clicked`() = runTest {
// SETUP
@ -144,8 +151,12 @@ class EditorCheckboxTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.onCheckboxClicked(view)
advanceUntilIdle()
verifyBlocking(updateCheckbox, times(1)) {
invoke(
eq(

View file

@ -12,11 +12,11 @@ import com.anytypeio.anytype.core_models.StubTitle
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
import com.anytypeio.anytype.domain.block.interactor.CreateBlock
import com.anytypeio.anytype.presentation.MockBlockFactory
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import com.jraska.livedata.test
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -53,7 +53,7 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -61,17 +61,19 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
stubSpaceManager()
stubGetNetworkMode()
stubFileLimitEvents()
stubAnalyticSpaceHelperDelegate()
}
@Test
fun `should ignore outside click if document isn't started yet`() {
fun `should ignore outside click if document isn't started yet`() = runTest {
val vm = buildViewModel()
vm.onOutsideClicked()
advanceUntilIdle()
verifyNoInteractions(createBlock)
}
@Test
fun `should create a new paragraph on outside-clicked event if page contains only title with icon`() {
fun `should create a new paragraph on outside-clicked event if page contains only title with icon`() = runTest {
// SETUP
@ -92,10 +94,14 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
// TESTING
vm.onOutsideClicked()
advanceUntilIdle()
verifyBlocking(createBlock, times(1)) {
async(
params = eq(
@ -113,7 +119,7 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
}
@Test
fun `should create a new paragraph on outside-clicked event if page contains only title with icon and one non-empty paragraph`() {
fun `should create a new paragraph on outside-clicked event if page contains only title with icon and one non-empty paragraph`() = runTest {
// SETUP
@ -145,10 +151,14 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
// TESTING
vm.onOutsideClicked()
advanceUntilIdle()
verifyBlocking(createBlock, times(1)) {
async(
params = eq(
@ -166,7 +176,7 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
}
@Test
fun `should create a new paragraph on outside-clicked event if the last block is a link block`() {
fun `should create a new paragraph on outside-clicked event if the last block is a link block`() = runTest {
// SETUP
@ -194,10 +204,14 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
vm.onStart(id = root.id, space = defaultSpace)
advanceUntilIdle()
// TESTING
vm.onOutsideClicked()
advanceUntilIdle()
verifyBlocking(createBlock, times(1)) {
async(
params = eq(
@ -214,83 +228,8 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
}
}
//@Test
fun `should not create a new paragraph but focus the last empty block`() {
// SETUP
val style = Block.Content.Text.Style.values().filter { style ->
style != Block.Content.Text.Style.TITLE || style != Block.Content.Text.Style.DESCRIPTION
}.random()
val pic = Block(
id = MockDataFactory.randomUuid(),
content = Block.Content.File(
type = Block.Content.File.Type.IMAGE,
state = Block.Content.File.State.DONE
),
fields = Block.Fields.empty(),
children = emptyList()
)
val txt = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields(emptyMap()),
content = Block.Content.Text(
text = "",
marks = emptyList(),
style = style
),
children = emptyList()
)
val doc = listOf(
Block(
id = root,
fields = Block.Fields(emptyMap()),
content = Block.Content.Smart,
children = listOf(pic.id, txt.id)
),
pic,
txt
)
stubInterceptEvents()
stubOpenDocument(document = doc)
val vm = buildViewModel()
// TESTING
vm.onStart(id = root, space = defaultSpace)
// Checking that no text block is focused
vm.state.test().assertValue { value ->
check(value is ViewState.Success)
value.blocks.none { it is BlockView.Text && it.isFocused }
}
vm.onOutsideClicked()
verifyNoInteractions(createBlock)
// Checking that the last text block is focused and has empty text
vm.state.test().assertValue { value ->
check(value is ViewState.Success)
val last = value.blocks.last()
check(last is BlockView.Text || last is BlockView.Code)
when (last) {
is BlockView.Code -> last.text.isEmpty() && last.isFocused
is BlockView.Text -> last.text.isEmpty() && last.isFocused
else -> throw IllegalStateException()
}
}
}
@Test
fun `should not create a new paragraph on outside-clicked event if object has restriction BLOCKS`() {
fun `should not create a new paragraph on outside-clicked event if object has restriction BLOCKS`() = runTest {
// SETUP
@ -311,15 +250,19 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
// TESTING
vm.onOutsideClicked()
advanceUntilIdle()
verifyNoInteractions(createBlock)
}
@Test
fun `should create a new paragraph on outside-clicked event if the last block is a table block`() {
fun `should create a new paragraph on outside-clicked event if the last block is a table block`() = runTest {
// SETUP
@ -343,10 +286,14 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
// TESTING
vm.onOutsideClicked()
advanceUntilIdle()
verifyBlocking(createBlock, times(1)) {
async(
params = eq(
@ -364,7 +311,7 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
}
@Test
fun `should create a new paragraph on outside-clicked event if the last block is a code snippet block`() {
fun `should create a new paragraph on outside-clicked event if the last block is a code snippet block`() = runTest {
// SETUP
@ -388,10 +335,14 @@ class EditorEmptySpaceInteractionTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
// TESTING
vm.onOutsideClicked()
advanceUntilIdle()
verifyBlocking(createBlock, times(1)) {
async(
params = eq(

View file

@ -3,12 +3,13 @@ package com.anytypeio.anytype.presentation.editor.editor
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.domain.base.Either
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlin.test.assertEquals
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runBlockingTest
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -24,7 +25,7 @@ class EditorErrorMessageTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -33,10 +34,11 @@ class EditorErrorMessageTest : EditorPresentationTestSetup() {
stubGetNetworkMode()
stubFileLimitEvents()
stubInterceptEvents()
stubAnalyticSpaceHelperDelegate()
}
@Test
fun `should not consume toast with message about downloading file if subscribed after message`() {
fun `should not consume toast with message about downloading file if subscribed after message`() = runTest {
val consumed = mutableListOf<String>()
@ -69,26 +71,27 @@ class EditorErrorMessageTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
runBlockingTest {
advanceUntilIdle()
val subscription1 = launch { vm.toasts.collect { consumed.add(it) } }
val subscription1 = launch { vm.toasts.collect { consumed.add(it) } }
// Launching operation that triggers a toast
// Launching operation that triggers a toast
vm.startDownloadingFile(blockId = file.id)
vm.startDownloadingFile(blockId = file.id)
val subscription2 = launch { vm.toasts.collect { consumed.add(it) } }
advanceUntilIdle()
subscription1.cancel()
subscription2.cancel()
val subscription2 = launch { vm.toasts.collect { consumed.add(it) } }
// Checking that we have only one toast event consumed by subscribers
subscription1.cancel()
subscription2.cancel()
assertEquals(
expected = 1,
actual = consumed.size
)
}
// Checking that we have only one toast event consumed by subscribers
assertEquals(
expected = 1,
actual = consumed.size
)
}
private fun stubDownloadFile() {

View file

@ -3,9 +3,11 @@ package com.anytypeio.anytype.presentation.editor.editor
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -21,7 +23,7 @@ class EditorEventSubscriptionTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -30,10 +32,11 @@ class EditorEventSubscriptionTest : EditorPresentationTestSetup() {
stubFileLimitEvents()
stubGetNetworkMode()
stubInterceptEvents()
stubAnalyticSpaceHelperDelegate()
}
@Test
fun `should subscribe only on start`() {
fun `should subscribe only on start`() = runTest {
// SETUP
@ -70,12 +73,18 @@ class EditorEventSubscriptionTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
verify(interceptEvents, times(1)).build(params)
vm.onStop()
advanceUntilIdle()
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
verify(interceptEvents, times(2)).build(params)
}
}

View file

@ -16,11 +16,12 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.editor.render.parseThemeBackgroundColor
import com.anytypeio.anytype.presentation.mapper.toView
import com.anytypeio.anytype.presentation.relations.ObjectRelationView
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import com.jraska.livedata.test
import kotlin.test.assertEquals
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import net.lachlanmckee.timberjunit.TimberTestRule
import org.junit.After
@ -44,7 +45,7 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -134,6 +135,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
@ -185,11 +188,6 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
val second = test.awaitValue()
second.assertValue(ViewState.Success(expected))
// assertEquals(
// expected = ViewState.Success(expected),
// actual = second
// )
}
@Test
@ -261,6 +259,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected =
listOf(
BlockView.Title.Basic(
@ -363,6 +363,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected =
listOf(
BlockView.Title.Basic(
@ -466,6 +468,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
@ -587,6 +591,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
@ -717,6 +723,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
@ -841,6 +849,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
@ -1074,6 +1084,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
@ -1165,6 +1177,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Profile(
id = title.id,
@ -1256,6 +1270,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Profile(
id = title.id,
@ -1344,6 +1360,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Profile(
id = title.id,
@ -1444,6 +1462,8 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Profile(
id = title.id,

View file

@ -15,11 +15,13 @@ import com.anytypeio.anytype.core_models.ext.content
import com.anytypeio.anytype.presentation.editor.EditorViewModel
import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState
import com.anytypeio.anytype.presentation.editor.editor.model.Focusable
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import com.jraska.livedata.test
import kotlin.test.assertEquals
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -34,7 +36,7 @@ class EditorFocusTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
private val title = Block(
id = MockDataFactory.randomUuid(),
@ -63,10 +65,11 @@ class EditorFocusTest : EditorPresentationTestSetup() {
stubGetNetworkMode()
stubFileLimitEvents()
stubInterceptEvents()
stubAnalyticSpaceHelperDelegate()
}
@Test
fun `should clear focus internally and re-render on hide-keyboard event`() {
fun `should clear focus internally and re-render on hide-keyboard event`() = runTest {
// SETUP
@ -104,6 +107,8 @@ class EditorFocusTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val testViewStateObserver = vm.state.test()
val testFocusObserver = vm.focus.test()
@ -120,15 +125,19 @@ class EditorFocusTest : EditorPresentationTestSetup() {
hasFocus = true
)
advanceUntilIdle()
testFocusObserver.assertValue(block.id)
vm.onHideKeyboardClicked()
advanceUntilIdle()
testFocusObserver.assertValue(EditorViewModel.EMPTY_FOCUS_ID)
}
@Test
fun `should focus on start if title is empty`() {
fun `should focus on start if title is empty`() = runTest {
// SETUP
@ -157,6 +166,8 @@ class EditorFocusTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val testViewStateObserver = vm.state.test()
val testFocusObserver = vm.focus.test()
@ -171,7 +182,7 @@ class EditorFocusTest : EditorPresentationTestSetup() {
}
@Test
fun `should not focus on start if title is not empty`() {
fun `should not focus on start if title is not empty`() = runTest {
// SETUP
@ -196,6 +207,8 @@ class EditorFocusTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val testViewStateObserver = vm.state.test()
val testFocusObserver = vm.focus.test()
@ -210,7 +223,7 @@ class EditorFocusTest : EditorPresentationTestSetup() {
}
@Test
fun `should update views on hide-keyboard event`() {
fun `should update views on hide-keyboard event`() = runTest {
// SETUP
@ -257,6 +270,8 @@ class EditorFocusTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.state.test().apply {
assertValue { value ->
check(value is ViewState.Success)
@ -271,8 +286,12 @@ class EditorFocusTest : EditorPresentationTestSetup() {
hasFocus = true
)
advanceUntilIdle()
vm.onHideKeyboardClicked()
advanceUntilIdle()
vm.state.test().apply {
assertValue { value ->
check(value is ViewState.Success)
@ -284,7 +303,7 @@ class EditorFocusTest : EditorPresentationTestSetup() {
vm.onOutsideClicked()
coroutineTestRule.advanceUntilIdle()
advanceUntilIdle()
vm.state.test().apply {
try {
@ -303,7 +322,7 @@ class EditorFocusTest : EditorPresentationTestSetup() {
}
@Test
fun `should close keyboard and clear focus when system close keyboard happened`() {
fun `should close keyboard and clear focus when system close keyboard happened`() = runTest {
// SETUP
@ -327,17 +346,27 @@ class EditorFocusTest : EditorPresentationTestSetup() {
// TESTING
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.onSelectionChanged(
id = paragraph.id,
selection = IntRange(0, 0)
)
advanceUntilIdle()
vm.onBlockFocusChanged(
id = paragraph.id,
hasFocus = true
)
advanceUntilIdle()
vm.onBackPressedCallback()
advanceUntilIdle()
vm.controlPanelViewState.test().assertValue(
ControlPanelState(
navigationToolbar = ControlPanelState.Toolbar.Navigation(isVisible = true)
@ -346,7 +375,7 @@ class EditorFocusTest : EditorPresentationTestSetup() {
}
@Test
fun `when set focus in text block - Main toolbar should be with Any type`() {
fun `when set focus in text block - Main toolbar should be with Any type`() = runTest {
// SETUP
val title = StubTitle()
@ -369,14 +398,17 @@ class EditorFocusTest : EditorPresentationTestSetup() {
// TESTING Click on text block
vm.apply {
onStart(id = root, space = defaultSpace)
advanceUntilIdle()
onBlockFocusChanged(
id = first.id,
hasFocus = true
)
advanceUntilIdle()
onSelectionChanged(
id = first.id,
selection = IntRange(0, 0)
)
advanceUntilIdle()
}
// EXPECTED
@ -398,7 +430,7 @@ class EditorFocusTest : EditorPresentationTestSetup() {
}
@Test
fun `when set focus in title block - Main toolbar should be with Title type`() {
fun `when set focus in title block - Main toolbar should be with Title type`() = runTest {
// SETUP
val title = StubTitle()
@ -421,14 +453,17 @@ class EditorFocusTest : EditorPresentationTestSetup() {
// TESTING Click on title block
vm.apply {
onStart(id = root, space = defaultSpace)
advanceUntilIdle()
onBlockFocusChanged(
id = title.id,
hasFocus = true
)
advanceUntilIdle()
onSelectionChanged(
id = title.id,
selection = IntRange(0, 0)
)
advanceUntilIdle()
}
// EXPECTED
@ -450,7 +485,7 @@ class EditorFocusTest : EditorPresentationTestSetup() {
}
@Test
fun `when set focus in cell block - Main toolbar should be with Cell type`() {
fun `when set focus in cell block - Main toolbar should be with Cell type`() = runTest {
// SETUP
val title = StubTitle()
@ -488,14 +523,17 @@ class EditorFocusTest : EditorPresentationTestSetup() {
// TESTING Click on cell block
vm.apply {
onStart(id = root, space = defaultSpace)
advanceUntilIdle()
onBlockFocusChanged(
id = cells[0].id,
hasFocus = true
)
advanceUntilIdle()
onSelectionChanged(
id = cells[0].id,
selection = IntRange(0, 0)
)
advanceUntilIdle()
}
// EXPECTED

View file

@ -181,11 +181,11 @@ class EditorInternalFlagsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
coroutineTestRule.advanceTime(1200)
advanceUntilIdle()
verifyNoInteractions(setObjectInternalFlags)
coroutineTestRule.advanceTime(100)
advanceUntilIdle()
}
@Test

View file

@ -15,12 +15,13 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.editor.render.parseThemeBackgroundColor
import com.anytypeio.anytype.presentation.navigation.AppNavigation
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.presentation.util.TXT
import com.anytypeio.anytype.test_utils.MockDataFactory
import com.jraska.livedata.test
import kotlin.test.assertEquals
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
@ -34,7 +35,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
val title = StubTitle()
@ -54,7 +55,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
}
@Test
fun `all views should be in edit mode when locked key is missing`() {
fun `all views should be in edit mode when locked key is missing`() = runTest {
// SETUP
@ -92,6 +93,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
@ -117,7 +120,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
}
@Test
fun `all views should be in edit mode when locked key is set to false`() {
fun `all views should be in edit mode when locked key is set to false`() = runTest {
// SETUP
@ -157,6 +160,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
@ -182,7 +187,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
}
@Test
fun `all views should be in read mode`() {
fun `all views should be in read mode`() = runTest {
// SETUP
@ -222,6 +227,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
@ -247,7 +254,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
}
@Test
fun `should navigate to target when clicking on link-to-object when page is locked`() {
fun `should navigate to target when clicking on link-to-object when page is locked`() = runTest {
// SETUP
val link = MockBlockFactory.link()
val target = link.content.asLink().target
@ -289,6 +296,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
// TESTING
val expected = listOf(
@ -323,6 +332,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
)
)
advanceUntilIdle()
// checking navigation command
testObserver.assertValue { value ->
@ -334,7 +345,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
}
@Test
fun `should navigate to target when clicking on mention when page is locked`() {
fun `should navigate to target when clicking on mention when page is locked`() = runTest {
// SETUP
@ -394,6 +405,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
// TESTING
val expected = listOf(
@ -437,6 +450,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
)
)
advanceUntilIdle()
// checking navigation command
testObserver.assertValue { value ->
@ -448,7 +463,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
}
@Test
fun `should open bookmark when clicking on bookmark when page is locked`() {
fun `should open bookmark when clicking on bookmark when page is locked`() = runTest {
// SETUP
@ -503,6 +518,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
// TESTING
val expected = listOf(
@ -544,6 +561,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
)
)
advanceUntilIdle()
// checking browsing command
testObserver.assertValue { value ->
@ -612,6 +631,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
// TESTING
val expected = listOf(
@ -648,9 +669,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
vm.onClickListener(ListenerType.File.View(fileBlockId))
// checking open-by-default-app command
coroutineTestRule.advanceUntilIdle()
advanceUntilIdle()
testObserver.assertValue { value ->
value is EventWrapper && value.peekContent() == Command.OpenFileByDefaultApp(
@ -661,7 +680,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
}
@Test
fun `should open picture in fullscreen when clicking on file when page is locked`() {
fun `should open picture in fullscreen when clicking on file when page is locked`() = runTest {
// SETUP
@ -720,6 +739,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
// TESTING
val expected = listOf(
@ -757,6 +778,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
vm.onClickListener(ListenerType.Picture.View(picture.id))
advanceUntilIdle()
// checking open-by-default-app command
testObserver.assertValue { value ->

View file

@ -10,9 +10,11 @@ import com.anytypeio.anytype.domain.block.interactor.MergeBlocks
import com.anytypeio.anytype.domain.block.interactor.UpdateText
import com.anytypeio.anytype.presentation.editor.EditorViewModel
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ -29,7 +31,7 @@ class EditorMergeTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -37,10 +39,11 @@ class EditorMergeTest : EditorPresentationTestSetup() {
stubSpaceManager()
stubGetNetworkMode()
stubFileLimitEvents()
stubAnalyticSpaceHelperDelegate()
}
@Test
fun `should update text and proceed with merging the first paragraph with the second on non-empty-block-backspace-pressed event`() {
fun `should update text and proceed with merging the first paragraph with the second on non-empty-block-backspace-pressed event`() = runTest {
val title = StubTitle()
val header = StubHeader(children = listOf(title.id))
@ -66,16 +69,23 @@ class EditorMergeTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.onBlockFocusChanged(
id = second.id,
hasFocus = true
)
advanceUntilIdle()
vm.onSelectionChanged(
id = second.id,
selection = IntRange(0, 0)
)
advanceUntilIdle()
val text = MockDataFactory.randomString()
val blockView = BlockView.Text.Paragraph(
@ -85,12 +95,17 @@ class EditorMergeTest : EditorPresentationTestSetup() {
vm.onTextBlockTextChanged(blockView)
advanceUntilIdle()
vm.onNonEmptyBlockBackspaceClicked(
id = second.id,
marks = emptyList(),
text = text
)
advanceUntilIdle()
coroutineTestRule.advanceTime(EditorViewModel.TEXT_CHANGES_DEBOUNCE_DURATION)
verifyBlocking(updateText, times(2)) {
@ -119,7 +134,7 @@ class EditorMergeTest : EditorPresentationTestSetup() {
}
@Test
fun `should merge two text blocks from two different divs`() {
fun `should merge two text blocks from two different divs`() = runTest {
// SETUP
@ -181,14 +196,20 @@ class EditorMergeTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.onBlockFocusChanged(b.id, true)
advanceUntilIdle()
vm.onNonEmptyBlockBackspaceClicked(
id = b.id,
text = b.content<Block.Content.Text>().text,
marks = b.content<Block.Content.Text>().marks
)
advanceUntilIdle()
coroutineTestRule.advanceTime(EditorViewModel.TEXT_CHANGES_DEBOUNCE_DURATION)
verifyBlocking(mergeBlocks, times(1)) {
@ -204,7 +225,7 @@ class EditorMergeTest : EditorPresentationTestSetup() {
}
@Test
fun `should merge two text blocks from the first of two divs`() {
fun `should merge two text blocks from the first of two divs`() = runTest {
// SETUP
@ -288,14 +309,20 @@ class EditorMergeTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.onBlockFocusChanged(d.id, true)
advanceUntilIdle()
vm.onNonEmptyBlockBackspaceClicked(
id = d.id,
text = d.content<Block.Content.Text>().text,
marks = d.content<Block.Content.Text>().marks
)
advanceUntilIdle()
coroutineTestRule.advanceTime(EditorViewModel.TEXT_CHANGES_DEBOUNCE_DURATION)
verifyBlocking(mergeBlocks, times(1)) {
@ -312,7 +339,7 @@ class EditorMergeTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `should not merge text block with the previous block if this previous block is not a text block`() {
fun `should not merge text block with the previous block if this previous block is not a text block`() = runTest {
// SETUP
@ -353,14 +380,20 @@ class EditorMergeTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.onBlockFocusChanged(b.id, true)
advanceUntilIdle()
vm.onNonEmptyBlockBackspaceClicked(
id = b.id,
text = b.content<Block.Content.Text>().text,
marks = b.content<Block.Content.Text>().marks
)
advanceUntilIdle()
coroutineTestRule.advanceTime(EditorViewModel.TEXT_CHANGES_DEBOUNCE_DURATION)
verifyNoInteractions(mergeBlocks)

View file

@ -13,13 +13,14 @@ import com.anytypeio.anytype.presentation.editor.EditorViewModel
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.editor.model.EditorFooter
import com.anytypeio.anytype.presentation.relations.ObjectRelationView
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import com.jraska.livedata.test
import kotlin.test.assertEquals
import kotlin.time.ExperimentalTime
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import net.lachlanmckee.timberjunit.TimberTestRule
import org.junit.After
import org.junit.Before
@ -42,7 +43,7 @@ class EditorNoteLayoutTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -50,6 +51,7 @@ class EditorNoteLayoutTest : EditorPresentationTestSetup() {
stubSpaceManager()
stubGetNetworkMode()
stubFileLimitEvents()
stubAnalyticSpaceHelperDelegate()
}
@OptIn(ExperimentalCoroutinesApi::class)
@ -60,7 +62,7 @@ class EditorNoteLayoutTest : EditorPresentationTestSetup() {
@ExperimentalTime
@Test
fun `should render featured relations block and show note header as footer`() = runBlocking {
fun `should render featured relations block and show note header as footer`() = runTest {
val featuredBlock = Block(
id = "featuredRelations",
@ -147,6 +149,8 @@ class EditorNoteLayoutTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.FeaturedRelation(
id = featuredBlock.id,
@ -178,7 +182,7 @@ class EditorNoteLayoutTest : EditorPresentationTestSetup() {
@ExperimentalTime
@Test
fun `should render featured relations block and not show note header as footer`() = runBlocking {
fun `should render featured relations block and not show note header as footer`() = runTest {
val featuredBlock = Block(
id = "featuredRelations",
@ -266,6 +270,8 @@ class EditorNoteLayoutTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val expected = listOf(
BlockView.FeaturedRelation(
id = featuredBlock.id,

View file

@ -98,6 +98,7 @@ import com.anytypeio.anytype.domain.unsplash.UnsplashRepository
import com.anytypeio.anytype.domain.workspace.FileLimitsEventChannel
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.editor.DocumentExternalEventReducer
@ -121,6 +122,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flowOf
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
@ -365,6 +367,9 @@ open class EditorPresentationTestSetup {
@Mock
lateinit var storelessSubscriptionContainer: StorelessSubscriptionContainer
@Mock
lateinit var analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
@Mock
lateinit var getNetworkMode: GetNetworkMode
@ -426,7 +431,9 @@ open class EditorPresentationTestSetup {
createTable = createTable,
fillTableRow = fillTableRow,
clearBlockContent = clearBlockContent,
clearBlockStyle = clearBlockStyle
clearBlockStyle = clearBlockStyle,
analyticsSpaceHelperDelegate = analyticSpaceHelperDelegate,
spaceManager = spaceManager
)
dispatcher = Dispatcher.Default()
@ -486,11 +493,12 @@ open class EditorPresentationTestSetup {
storelessSubscriptionContainer = storelessSubscriptionContainer,
dispatchers = dispatchers,
getNetworkMode = getNetworkMode,
params = EditorViewModel.Params(
vmParams = EditorViewModel.Params(
ctx = root,
space = SpaceId(defaultSpace)
),
permissions = permissions
permissions = permissions,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
}
@ -840,7 +848,17 @@ open class EditorPresentationTestSetup {
)
}
fun stubAnalyticSpaceHelperDelegate() {
Mockito.`when`(analyticSpaceHelperDelegate.provideParams(defaultSpace))
.thenReturn(AnalyticSpaceHelperDelegate.Params.EMPTY)
analyticSpaceHelperDelegate.stub {
on { provideParams(defaultSpace) } doReturn AnalyticSpaceHelperDelegate.Params.EMPTY
}
}
fun proceedWithDefaultBeforeTestStubbing() {
stubAnalyticSpaceHelperDelegate()
stubSpaceManager()
stubUserPermission()
stubGetNetworkMode()

View file

@ -12,13 +12,15 @@ import com.anytypeio.anytype.presentation.editor.EditorViewModel.Companion.TEXT_
import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashItem
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import com.jraska.livedata.test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
@ -35,7 +37,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -47,6 +49,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
stubDuplicateBlock("", emptyList())
stubCopy()
stubPaste()
stubAnalyticSpaceHelperDelegate()
}
@OptIn(ExperimentalCoroutinesApi::class)
@ -57,7 +60,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
//region {Action DELETE}
@Test
fun `should not hide slash widget when action delete happened`() {
fun `should not hide slash widget when action delete happened`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -72,23 +75,29 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.Delete)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
assertNotNull(state)
@ -96,7 +105,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
}
@Test
fun `should send unlinkBlocks UseCase when action Delete happened`() {
fun `should send unlinkBlocks UseCase when action Delete happened`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -106,27 +115,34 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
stubSearchObjects()
stubOpenDocument(document = doc)
stubUnlinkBlocks()
val vm = buildViewModel()
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.Delete)
advanceUntilIdle()
val params = UnlinkBlocks.Params(
context = root,
targets = listOf(block.id)
@ -138,7 +154,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
}
@Test
fun `should not triggered unlinkBlocks UseCase when no blocks in focus`() {
fun `should not triggered unlinkBlocks UseCase when no blocks in focus`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -149,6 +165,8 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onSlashTextWatcherEvent(
SlashEvent.Start(
@ -156,12 +174,15 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.Delete)
advanceUntilIdle()
val params = UnlinkBlocks.Params(
context = root,
targets = listOf(block.id)
@ -172,7 +193,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
//region {Action DUPLICATE}
@Test
fun `should hide slash widget after action Duplicate`() {
fun `should hide slash widget after action Duplicate`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -184,23 +205,29 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.Duplicate)
advanceUntilIdle()
val stateAfter = vm.controlPanelViewState.value
assertNotNull(stateAfter)
@ -217,7 +244,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
}
@Test
fun `should invoke duplicateBlock UseCase after action Duplicate`() {
fun `should invoke duplicateBlock UseCase after action Duplicate`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -229,23 +256,29 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.Duplicate)
advanceUntilIdle()
val params = DuplicateBlock.Params(
context = root,
target = block.id,
@ -257,7 +290,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
//region {Action COPY}
@Test
fun `should hide slash widget after action Copy`() {
fun `should hide slash widget after action Copy`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -268,23 +301,29 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.Copy)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
assertNotNull(state)
@ -292,7 +331,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
}
@Test
fun `should send Copy UseCase with null range after action Copy`() {
fun `should send Copy UseCase with null range after action Copy`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -306,23 +345,29 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.Copy)
advanceUntilIdle()
val params = Copy.Params(
context = root,
range = null,
@ -335,7 +380,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
//region {Action PASTE}
@Test
fun `should hide slash widget after action Paste`() {
fun `should hide slash widget after action Paste`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -345,23 +390,29 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.Paste)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
assertNotNull(state)
@ -369,7 +420,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
}
@Test
fun `should send Paste UseCase with selection range after action Paste`() {
fun `should send Paste UseCase with selection range after action Paste`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -381,26 +432,34 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSelectionChanged(
id = block.id,
selection = IntRange(3, 3)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 3
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.Paste)
advanceUntilIdle()
val focus = vm.focus.value
assertNotNull(focus)
@ -417,7 +476,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
//region {Action MOVE}
@Test
fun `should hide slash widget after action Move`() {
fun `should hide slash widget after action Move`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -427,23 +486,29 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.Move)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
assertNotNull(state)
@ -451,7 +516,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
}
@Test
fun `should enter mode SAM after action Move`() {
fun `should enter mode SAM after action Move`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -461,23 +526,29 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.Move)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
assertNotNull(state)
@ -495,7 +566,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
//region {Action MOVE TO}
@Test
fun `should hide slash widget and navigate to move to screen after move to action`() {
fun `should hide slash widget and navigate to move to screen after move to action`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -505,23 +576,29 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.MoveTo)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
assertNotNull(state)
@ -540,7 +617,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
//region {Action CLEAN STYLE}
@Test
fun `should hide slash widget after action Clean Style`() {
fun `should hide slash widget after action Clean Style`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -550,23 +627,29 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.CleanStyle)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
assertNotNull(state)
@ -574,7 +657,7 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
}
@Test
fun `should not send UpdateText UseCase after action Clean Style`() {
fun `should not send UpdateText UseCase after action Clean Style`() = runTest {
val header = MockTypicalDocumentFactory.header
val title = MockTypicalDocumentFactory.title
@ -621,23 +704,29 @@ class EditorSlashWidgetActionsTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Actions.CleanStyle)
advanceUntilIdle()
val params = UpdateText.Params(
context = root,
target = block.id,

View file

@ -15,10 +15,11 @@ import com.anytypeio.anytype.presentation.editor.editor.slash.SlashWidgetState
import com.anytypeio.anytype.presentation.number.NumberParser
import com.anytypeio.anytype.presentation.objects.ObjectTypeView
import com.anytypeio.anytype.presentation.relations.ObjectRelationView
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
@ -31,7 +32,7 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
val rule = InstantTaskExecutorRule()
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -56,7 +57,7 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
//region {STYLE}
@Test
fun `should return Update command with style items when click on style item`() {
fun `should return Update command with style items when click on style item`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -68,6 +69,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
@ -81,6 +84,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
// TESTING
val event = SlashEvent.Filter(filter = "/", viewType = Types.HOLDER_NUMBERED)
@ -88,6 +93,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onSlashTextWatcherEvent(event = event)
vm.onSlashItemClicked(SlashItem.Main.Style)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val stateWidget = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -127,7 +134,7 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
}
@Test
fun `should return Update command with style items without bold and italic`() {
fun `should return Update command with style items without bold and italic`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -139,6 +146,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
@ -152,6 +161,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
// TESTING
val event = SlashEvent.Filter(filter = "/", viewType = Types.HOLDER_HEADER_TWO)
@ -159,6 +170,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onSlashTextWatcherEvent(event = event)
vm.onSlashItemClicked(SlashItem.Main.Style)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val stateWidget = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -197,7 +210,7 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
//region {MEDIA}
@Test
fun `should return Update command with media items when click on media item`() {
fun `should return Update command with media items when click on media item`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -209,6 +222,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
@ -222,6 +237,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
// TESTING
val event = SlashEvent.Filter(filter = "/", viewType = Types.HOLDER_NUMBERED)
@ -229,6 +246,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onSlashTextWatcherEvent(event = event)
vm.onSlashItemClicked(SlashItem.Main.Media)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val stateWidget = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -297,19 +316,19 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
stubInterceptEvents()
stubOpenDocument(document = doc)
stubGetObjectTypes((listOf(type2, type1, type3)))
// stubSearchObjects(
// objects = listOf(type1, type2, type3)
// )
val vm = buildViewModel()
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
@ -318,13 +337,20 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
// TESTING
val event = SlashEvent.Filter(filter = "/", viewType = Types.HOLDER_NUMBERED)
vm.onSlashTextWatcherEvent(event = event)
advanceUntilIdle()
vm.onSlashItemClicked(SlashItem.Main.Objects)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val stateWidget = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -471,6 +497,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = a.id,
@ -484,6 +512,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
// TESTING
val event = SlashEvent.Filter(filter = "/", viewType = Types.HOLDER_NUMBERED)
@ -491,6 +521,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onSlashTextWatcherEvent(event = event)
vm.onSlashItemClicked(SlashItem.Main.Relations)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val stateWidget = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -550,7 +582,7 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
//region {OTHERS}
@Test
fun `should return Update command with other items when click on Other item`() {
fun `should return Update command with other items when click on Other item`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -562,6 +594,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
@ -575,6 +609,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
// TESTING
val event = SlashEvent.Filter(filter = "/", viewType = Types.HOLDER_NUMBERED)
@ -582,6 +618,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onSlashTextWatcherEvent(event = event)
vm.onSlashItemClicked(SlashItem.Main.Other)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val stateWidget = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -614,7 +652,7 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
//region {ACTIONS}
@Test
fun `should return Update command with actions items when click on Action item(Stable Build)`() {
fun `should return Update command with actions items when click on Action item(Stable Build)`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -626,6 +664,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
@ -639,6 +679,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
// TESTING
val event = SlashEvent.Filter(filter = "/", viewType = Types.HOLDER_NUMBERED)
@ -646,6 +688,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onSlashTextWatcherEvent(event = event)
vm.onSlashItemClicked(SlashItem.Main.Actions)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val stateWidget = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -680,7 +724,7 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
//region {ALIGNMENT}
@Test
fun `should return Update command with alignment items when click on Alignment item`() {
fun `should return Update command with alignment items when click on Alignment item`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -692,6 +736,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
@ -705,6 +751,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
// TESTING
val event = SlashEvent.Filter(filter = "/", viewType = Types.HOLDER_PARAGRAPH)
@ -712,6 +760,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onSlashTextWatcherEvent(event = event)
vm.onSlashItemClicked(SlashItem.Main.Alignment)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val stateWidget = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -741,7 +791,7 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
}
@Test
fun `should return Update command with no alignment items when click on alignment item for numbers views`() {
fun `should return Update command with no alignment items when click on alignment item for numbers views`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -753,6 +803,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
@ -766,6 +818,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
// TESTING
val event = SlashEvent.Filter(filter = "/", viewType = Types.HOLDER_NUMBERED)
@ -773,6 +827,8 @@ class EditorSlashWidgetClicksTest: EditorPresentationTestSetup() {
vm.onSlashTextWatcherEvent(event = event)
vm.onSlashItemClicked(SlashItem.Main.Alignment)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val stateWidget = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems

View file

@ -13,12 +13,14 @@ import com.anytypeio.anytype.presentation.editor.EditorViewModel.Companion.TEXT_
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashItem
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashWidgetState
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
@ -39,7 +41,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -48,6 +50,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
stubGetNetworkMode()
stubFileLimitEvents()
stubUpdateText()
stubAnalyticSpaceHelperDelegate()
}
@OptIn(ExperimentalCoroutinesApi::class)
@ -58,7 +61,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
//region {TEXT COLOR}
@Test
fun `should selected red color when block text color is red`() {
fun `should selected red color when block text color is red`() = runTest {
val code = ThemeColor.RED.code
@ -98,23 +101,29 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Main.Color)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val command = state?.slashWidget?.widgetState
@ -143,7 +152,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
}
@Test
fun `should selected default color when block text color is null`() {
fun `should selected default color when block text color is null`() = runTest {
val code: String? = null
@ -183,23 +192,29 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Main.Color)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val command = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -228,7 +243,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
}
@Test
fun `should selected default color when block text color is default`() {
fun `should selected default color when block text color is default`() = runTest {
val code: String = ThemeColor.DEFAULT.code
@ -268,23 +283,29 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Main.Color)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val command = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -313,7 +334,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
}
@Test
fun `should save selection and focus when text color picked`() {
fun `should save selection and focus when text color picked`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -324,6 +345,8 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(4, 4)
vm.apply {
@ -331,10 +354,12 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
id = block.id,
selection = selection
)
advanceUntilIdle()
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
@ -346,7 +371,9 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
// TESTING
vm.onSlashItemClicked(SlashItem.Main.Color)
advanceUntilIdle()
vm.onSlashItemClicked(SlashItem.Color.Text(themeColor = ThemeColor.RED, isSelected = false))
advanceUntilIdle()
val focus = orchestrator.stores.focus.current()
val cursor = Editor.Cursor.Range(range = selection)
@ -356,7 +383,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
}
@Test
fun `should hide slash widget when text color picked`() {
fun `should hide slash widget when text color picked`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -367,23 +394,29 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Main.Color)
advanceUntilIdle()
vm.onSlashItemClicked(SlashItem.Color.Text(themeColor = ThemeColor.RED, isSelected = false))
advanceUntilIdle()
val state = vm.controlPanelViewState.value
@ -392,7 +425,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
}
@Test
fun `should send updateTextColor UseCase when text color picked`() {
fun `should send updateTextColor UseCase when text color picked`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -405,17 +438,21 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
@ -423,7 +460,10 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
val code = ThemeColor.ICE.code
vm.onSlashItemClicked(SlashItem.Main.Color)
advanceUntilIdle()
vm.onSlashItemClicked(SlashItem.Color.Text(themeColor = ThemeColor.ICE, isSelected = false))
advanceUntilIdle()
val params = UpdateTextColor.Params(
context = root,
@ -438,7 +478,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
//region {BACKGROUND COLOR}
@Test
fun `should selected green color when block background color is green`() {
fun `should selected green color when block background color is green`() = runTest {
val code = ThemeColor.LIME.code
@ -480,23 +520,29 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Main.Background)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val command = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -525,7 +571,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
}
@Test
fun `should selected default color when block background color is null`() {
fun `should selected default color when block background color is null`() = runTest {
val code: String? = null
@ -567,23 +613,29 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Main.Background)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val command = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -612,7 +664,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
}
@Test
fun `should selected default color when block background color is default`() {
fun `should selected default color when block background color is default`() = runTest {
val code: String = ThemeColor.DEFAULT.code
@ -654,23 +706,29 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Main.Background)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
val command = state?.slashWidget?.widgetState as SlashWidgetState.UpdateItems
@ -699,7 +757,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
}
@Test
fun `should save selection and focus when background color picked`() {
fun `should save selection and focus when background color picked`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -712,6 +770,8 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(4, 4)
vm.apply {
@ -720,10 +780,15 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
selection = selection
)
advanceUntilIdle()
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
@ -735,8 +800,13 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
// TESTING
vm.onSlashItemClicked(SlashItem.Main.Background)
advanceUntilIdle()
vm.onSlashItemClicked(SlashItem.Color.Background(themeColor = ThemeColor.RED, isSelected = false))
advanceUntilIdle()
val focus = orchestrator.stores.focus.current()
val cursor = Editor.Cursor.Range(range = selection)
@ -745,7 +815,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
}
@Test
fun `should hide slash widget when background color picked`() {
fun `should hide slash widget when background color picked`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -758,23 +828,29 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Main.Background)
advanceUntilIdle()
vm.onSlashItemClicked(SlashItem.Color.Background(themeColor = ThemeColor.RED, isSelected = false))
advanceUntilIdle()
val state = vm.controlPanelViewState.value
@ -783,7 +859,7 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
}
@Test
fun `should send updateBackgroundColor UseCase when background color picked`() {
fun `should send updateBackgroundColor UseCase when background color picked`() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -796,17 +872,21 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
@ -814,7 +894,9 @@ class EditorSlashWidgetColorTest : EditorPresentationTestSetup() {
val code = ThemeColor.PURPLE.code
vm.onSlashItemClicked(SlashItem.Main.Background)
advanceUntilIdle()
vm.onSlashItemClicked(SlashItem.Color.Background(themeColor = ThemeColor.PURPLE, isSelected = false))
advanceUntilIdle()
val params = UpdateBackgroundColor.Params(
context = root,

View file

@ -9,9 +9,11 @@ import com.anytypeio.anytype.presentation.editor.EditorViewModel.Companion.TEXT_
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashItem
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
@ -32,7 +34,7 @@ class EditorSlashWidgetCutFilterTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@Before
fun setup() {
@ -41,6 +43,7 @@ class EditorSlashWidgetCutFilterTest : EditorPresentationTestSetup() {
stubGetNetworkMode()
stubFileLimitEvents()
stubGetObjectTypes(emptyList())
stubAnalyticSpaceHelperDelegate()
}
@OptIn(ExperimentalCoroutinesApi::class)
@ -121,7 +124,7 @@ class EditorSlashWidgetCutFilterTest : EditorPresentationTestSetup() {
private fun `should invoke updateText useCase when clicked on Slash Item Style`(
slashItem: SlashItem
) {
) = runTest {
val header = MockTypicalDocumentFactory.header
val title = MockTypicalDocumentFactory.title
@ -160,27 +163,33 @@ class EditorSlashWidgetCutFilterTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onSelectionChanged(
id = block.id,
selection = IntRange(3, 3)
)
advanceUntilIdle()
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Start(
cursorCoordinate = 820,
slashStart = 3
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = 0
)
)
advanceUntilIdle()
onTextBlockTextChanged(
view = BlockView.Text.Paragraph(
id = block.id,
@ -197,16 +206,19 @@ class EditorSlashWidgetCutFilterTest : EditorPresentationTestSetup() {
cursor = null
)
)
advanceUntilIdle()
onSelectionChanged(
id = block.id,
selection = IntRange(4, 4)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/s",
viewType = 0
)
)
advanceUntilIdle()
onTextBlockTextChanged(
view = BlockView.Text.Paragraph(
id = block.id,
@ -223,16 +235,19 @@ class EditorSlashWidgetCutFilterTest : EditorPresentationTestSetup() {
cursor = null
)
)
advanceUntilIdle()
onSelectionChanged(
id = block.id,
selection = IntRange(5, 5)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/su",
viewType = 0
)
)
advanceUntilIdle()
onTextBlockTextChanged(
view = BlockView.Text.Paragraph(
id = block.id,
@ -249,10 +264,12 @@ class EditorSlashWidgetCutFilterTest : EditorPresentationTestSetup() {
cursor = null
)
)
advanceUntilIdle()
onSelectionChanged(
id = block.id,
selection = IntRange(6, 6)
)
advanceUntilIdle()
}
//TESTING
@ -261,6 +278,8 @@ class EditorSlashWidgetCutFilterTest : EditorPresentationTestSetup() {
item = slashItem
)
advanceUntilIdle()
val params = UpdateText.Params(
context = root,
target = block.id,

View file

@ -11,12 +11,14 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashItem
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import net.lachlanmckee.timberjunit.TimberTestRule
import org.junit.After
import org.junit.Before
@ -33,7 +35,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
@get:Rule
val timberTestRule: TimberTestRule = TimberTestRule.builder()
@ -49,6 +51,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
stubSpaceManager()
stubGetNetworkMode()
stubFileLimitEvents()
stubAnalyticSpaceHelperDelegate()
}
@After
@ -76,7 +79,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
//region {1}
@Test
fun `should hide slash widget when clicked on BOLD `() {
fun `should hide slash widget when clicked on BOLD `() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -90,165 +93,42 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onSelectionChanged(
id = block.id,
selection = IntRange(0, 0)
)
advanceUntilIdle()
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Style.Markup.Bold)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
assertNotNull(state)
assertFalse(state.slashWidget.isVisible)
}
fun `should invoke update markup Bold command`() {
val header = MockTypicalDocumentFactory.header
val title = MockTypicalDocumentFactory.title
val block = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.Text(
text = "FooBar",
marks = listOf(),
style = Block.Content.Text.Style.P
)
)
val page = Block(
id = root,
fields = Block.Fields(emptyMap()),
content = Block.Content.Smart,
children = listOf(header.id, block.id)
)
val doc = listOf(page, header, title, block)
stubInterceptEvents()
stubUpdateBlocksMark()
stubOpenDocument(document = doc)
val vm = buildViewModel()
vm.onStart(id = root, space = defaultSpace)
vm.apply {
onSelectionChanged(
id = block.id,
selection = IntRange(3, 3)
)
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
onSlashTextWatcherEvent(
event = SlashEvent.Start(
cursorCoordinate = 820,
slashStart = 3
)
)
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = 0
)
)
onTextBlockTextChanged(
view = BlockView.Text.Paragraph(
id = block.id,
text = "Foo/Bar",
marks = listOf(),
isFocused = true,
mode = BlockView.Mode.EDIT,
isSelected = false,
cursor = null
)
)
onSelectionChanged(
id = block.id,
selection = IntRange(4, 4)
)
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/b",
viewType = 0
)
)
onTextBlockTextChanged(
view = BlockView.Text.Paragraph(
id = block.id,
text = "Foo/bBar",
marks = listOf(),
isFocused = true,
mode = BlockView.Mode.EDIT,
isSelected = false,
cursor = null
)
)
onSelectionChanged(
id = block.id,
selection = IntRange(5, 5)
)
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/bo",
viewType = 0
)
)
onTextBlockTextChanged(
view = BlockView.Text.Paragraph(
id = block.id,
text = "Foo/boBar",
marks = listOf(),
isFocused = true,
mode = BlockView.Mode.EDIT,
isSelected = false,
cursor = null
)
)
onSelectionChanged(
id = block.id,
selection = IntRange(6, 6)
)
}
//TESTING
vm.onSlashItemClicked(
item = SlashItem.Style.Markup.Bold
)
val params = UpdateBlocksMark.Params(
context = root,
targets = listOf(block.id),
mark = Block.Content.Text.Mark(
range = IntRange(0, block.content.asText().text.length),
type = Block.Content.Text.Mark.Type.BOLD
)
)
verifyBlocking(updateBlocksMark, times(1)) { invoke(params) }
}
@Test
fun `should save selection and focus on slash start index when clicked on BOLD`() {
fun `should save selection and focus on slash start index when clicked on BOLD`() = runTest {
val header = MockTypicalDocumentFactory.header
val title = MockTypicalDocumentFactory.title
@ -303,6 +183,8 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(7, 7)
vm.apply {
@ -310,28 +192,34 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
id = block.id,
selection = selection
)
advanceUntilIdle()
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 7
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = 0
)
)
advanceUntilIdle()
}
//TESTING
vm.onSlashItemClicked(SlashItem.Style.Markup.Bold)
advanceUntilIdle()
val focus = orchestrator.stores.focus.current()
val cursor = Editor.Cursor.Range(range = selection)
@ -340,7 +228,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
}
@Test
fun `should invoke updateBlocksMark when clicked on BOLD`() {
fun `should invoke updateBlocksMark when clicked on BOLD`() = runTest {
val header = MockTypicalDocumentFactory.header
val title = MockTypicalDocumentFactory.title
@ -400,6 +288,8 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(7, 7)
vm.apply {
@ -407,22 +297,26 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
id = block2.id,
selection = selection
)
advanceUntilIdle()
onBlockFocusChanged(
id = block2.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 7
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = Types.HOLDER_BULLET
)
)
advanceUntilIdle()
onTextBlockTextChanged(
view = BlockView.Text.Paragraph(
id = block2.id,
@ -434,6 +328,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
cursor = null
)
)
advanceUntilIdle()
}
coroutineTestRule.advanceTime(300)
@ -442,6 +337,8 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onSlashItemClicked(SlashItem.Style.Markup.Bold)
advanceUntilIdle()
val params = UpdateBlocksMark.Params(
context = root,
targets = listOf(block2.id),
@ -457,7 +354,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
//region {2}
@Test
fun `should hide slash widget event when clicked on ITALIC `() {
fun `should hide slash widget event when clicked on ITALIC `() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -471,33 +368,41 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onSelectionChanged(
id = block.id,
selection = IntRange(0, 0)
)
advanceUntilIdle()
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Style.Markup.Italic)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
assertNotNull(state)
@ -505,7 +410,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
}
@Test
fun `should save selection and focus when clicked on ITALIC`() {
fun `should save selection and focus when clicked on ITALIC`() = runTest {
val header = MockTypicalDocumentFactory.header
val title = MockTypicalDocumentFactory.title
@ -560,6 +465,8 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(11, 11)
vm.apply {
@ -567,28 +474,34 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
id = block.id,
selection = selection
)
advanceUntilIdle()
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 11
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = 0
)
)
advanceUntilIdle()
}
//TESTING
vm.onSlashItemClicked(SlashItem.Style.Markup.Italic)
advanceUntilIdle()
val focus = orchestrator.stores.focus.current()
val cursor = Editor.Cursor.Range(range = selection)
@ -597,7 +510,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
}
@Test
fun `should invoke updateBlocksMark when clicked on ITALIC`() {
fun `should invoke updateBlocksMark when clicked on ITALIC`() = runTest {
val header = MockTypicalDocumentFactory.header
val title = MockTypicalDocumentFactory.title
@ -641,6 +554,8 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(7, 7)
vm.apply {
@ -648,22 +563,26 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
id = block2.id,
selection = selection
)
advanceUntilIdle()
onBlockFocusChanged(
id = block2.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 7
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = 0
)
)
advanceUntilIdle()
onTextBlockTextChanged(
view = BlockView.Text.Paragraph(
id = block2.id,
@ -675,12 +594,15 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
cursor = null
)
)
advanceUntilIdle()
}
//TESTING
vm.onSlashItemClicked(SlashItem.Style.Markup.Italic)
advanceUntilIdle()
val params = UpdateBlocksMark.Params(
context = root,
targets = listOf(block2.id),
@ -696,7 +618,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
//region {3}
@Test
fun `should hide slash widget event when clicked on STRIKETHROUGH `() {
fun `should hide slash widget event when clicked on STRIKETHROUGH `() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -710,27 +632,34 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onSelectionChanged(
id = block.id,
selection = IntRange(0, 0)
)
advanceUntilIdle()
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Style.Markup.Strikethrough)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
assertNotNull(state)
@ -738,7 +667,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
}
@Test
fun `should save selection and focus when clicked on STRIKETHROUGH`() {
fun `should save selection and focus when clicked on STRIKETHROUGH`() = runTest {
val header = MockTypicalDocumentFactory.header
val title = MockTypicalDocumentFactory.title
@ -793,6 +722,8 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(5, 5)
vm.apply {
@ -800,28 +731,34 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
id = block2.id,
selection = selection
)
advanceUntilIdle()
onBlockFocusChanged(
id = block2.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 5
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = 0
)
)
advanceUntilIdle()
}
//TESTING
vm.onSlashItemClicked(SlashItem.Style.Markup.Strikethrough)
advanceUntilIdle()
val focus = orchestrator.stores.focus.current()
val cursor = Editor.Cursor.Range(range = selection)
@ -830,7 +767,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
}
@Test
fun `should invoke updateBlocksMark when clicked on STRIKETHROUGH`() {
fun `should invoke updateBlocksMark when clicked on STRIKETHROUGH`() = runTest {
val header = MockTypicalDocumentFactory.header
val title = MockTypicalDocumentFactory.title
@ -874,6 +811,8 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(7, 7)
vm.apply {
@ -881,22 +820,26 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
id = block.id,
selection = selection
)
advanceUntilIdle()
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 7
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = 0
)
)
advanceUntilIdle()
onTextBlockTextChanged(
view = BlockView.Text.Paragraph(
id = block.id,
@ -908,12 +851,15 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
cursor = null
)
)
advanceUntilIdle()
}
//TESTING
vm.onSlashItemClicked(SlashItem.Style.Markup.Strikethrough)
advanceUntilIdle()
val params = UpdateBlocksMark.Params(
context = root,
targets = listOf(block.id),
@ -929,7 +875,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
//region {4}
@Test
fun `should hide slash widget event when clicked on CODE `() {
fun `should hide slash widget event when clicked on CODE `() = runTest {
val doc = MockTypicalDocumentFactory.page(root)
val block = MockTypicalDocumentFactory.a
@ -943,33 +889,41 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onSelectionChanged(
id = block.id,
selection = IntRange(0, 0)
)
advanceUntilIdle()
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 0
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = 0
)
)
advanceUntilIdle()
}
// TESTING
vm.onSlashItemClicked(SlashItem.Style.Markup.Code)
advanceUntilIdle()
val state = vm.controlPanelViewState.value
assertNotNull(state)
@ -977,7 +931,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
}
@Test
fun `should save selection and focus when clicked on CODE`() {
fun `should save selection and focus when clicked on CODE`() = runTest {
val header = MockTypicalDocumentFactory.header
val title = MockTypicalDocumentFactory.title
@ -1032,6 +986,8 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(15, 15)
vm.apply {
@ -1039,28 +995,34 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
id = block3.id,
selection = selection
)
advanceUntilIdle()
onBlockFocusChanged(
id = block3.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 15
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = 0
)
)
advanceUntilIdle()
}
//TESTING
vm.onSlashItemClicked(SlashItem.Style.Markup.Code)
advanceUntilIdle()
val focus = orchestrator.stores.focus.current()
val cursor = Editor.Cursor.Range(range = selection)
@ -1069,7 +1031,7 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
}
@Test
fun `should invoke updateBlocksMark when clicked on CODE`() {
fun `should invoke updateBlocksMark when clicked on CODE`() = runTest {
val header = MockTypicalDocumentFactory.header
val title = MockTypicalDocumentFactory.title
@ -1113,6 +1075,8 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(7, 7)
vm.apply {
@ -1120,22 +1084,26 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
id = block.id,
selection = selection
)
advanceUntilIdle()
onBlockFocusChanged(
id = block.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 7
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
viewType = 0
)
)
advanceUntilIdle()
onTextBlockTextChanged(
view = BlockView.Text.Paragraph(
id = block.id,
@ -1147,12 +1115,15 @@ class EditorSlashWidgetMarksTest : EditorPresentationTestSetup() {
cursor = null
)
)
advanceUntilIdle()
}
//TESTING
vm.onSlashItemClicked(SlashItem.Style.Markup.Code)
advanceUntilIdle()
val params = UpdateBlocksMark.Params(
context = root,
targets = listOf(block.id),

View file

@ -17,8 +17,10 @@ import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashItem
import com.anytypeio.anytype.presentation.objects.ObjectTypeView
import com.anytypeio.anytype.presentation.objects.getProperName
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
@ -34,7 +36,7 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule()
val space = defaultSpace
@ -45,6 +47,7 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
stubGetNetworkMode()
stubFileLimitEvents()
stubClosePage()
stubAnalyticSpaceHelperDelegate()
}
@OptIn(ExperimentalCoroutinesApi::class)
@ -54,7 +57,7 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
}
@Test
fun `should invoke CreateBlockLinkWithObject UseCase on clicked on object type item with bottom position when text block is not empty`() {
fun `should invoke CreateBlockLinkWithObject UseCase on clicked on object type item with bottom position when text block is not empty`() = runTest {
// SETUP
val doc = MockTypicalDocumentFactory.page(root)
val a = MockTypicalDocumentFactory.a
@ -71,16 +74,23 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
stubSpaceManager(defaultSpace)
val vm = buildViewModel()
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(a.id, true)
advanceUntilIdle()
onSlashTextWatcherEvent(SlashEvent.Start(100, 0))
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Filter(
filter = "/",
viewType = Types.HOLDER_NUMBERED
)
)
advanceUntilIdle()
}
// TESTING
@ -97,6 +107,8 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
)
)
advanceUntilIdle()
val params = CreateBlockLinkWithObject.Params(
context = root,
target = a.id,
@ -111,7 +123,7 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
}
@Test
fun `should invoke CreateBlockLinkWithObject UseCase on clicked on object type item with replace position when text block is empty`() {
fun `should invoke CreateBlockLinkWithObject UseCase on clicked on object type item with replace position when text block is empty`() = runTest {
// SETUP
val paragraph = StubParagraph(text = "")
@ -132,15 +144,21 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
val vm = buildViewModel()
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
vm.apply {
onBlockFocusChanged(paragraph.id, true)
advanceUntilIdle()
onSlashTextWatcherEvent(SlashEvent.Start(1, 0))
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Filter(
filter = "/",
viewType = Types.HOLDER_NUMBERED
)
)
advanceUntilIdle()
}
// TESTING
@ -157,6 +175,8 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
)
)
advanceUntilIdle()
val params = CreateBlockLinkWithObject.Params(
context = root,
target = paragraph.id,
@ -167,6 +187,8 @@ class EditorSlashWidgetObjectTypeTest : EditorPresentationTestSetup() {
template = null
)
advanceUntilIdle()
verifyBlocking(createBlockLinkWithObject, times(1)) { async(params) }
}
}

View file

@ -17,12 +17,14 @@ import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashItem
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashRelationView
import com.anytypeio.anytype.presentation.relations.ObjectRelationView
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import com.anytypeio.anytype.presentation.util.TXT
import com.anytypeio.anytype.test_utils.MockDataFactory
import com.jraska.livedata.test
import kotlin.test.assertEquals
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import net.lachlanmckee.timberjunit.TimberTestRule
import org.junit.After
@ -40,7 +42,7 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
val coroutineTestRule = DefaultCoroutineTestRule(StandardTestDispatcher())
@get:Rule
val timberTestRule: TimberTestRule = TimberTestRule.builder()
@ -58,7 +60,7 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
@After
fun after() {
coroutineTestRule.advanceTime(EditorViewModel.TEXT_CHANGES_DEBOUNCE_DURATION)
coroutineTestRule.advanceUntilIdle()
}
@Test
@ -86,16 +88,20 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
details = customDetails
)
val vm = buildViewModel()
storeOfRelations.merge(
listOf(r1, r2, r3)
)
val vm = buildViewModel()
// TESTING
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(1, 1)
vm.apply {
onSelectionChanged(
id = a.id,
@ -119,6 +125,8 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
vm.onSlashItemClicked(
SlashItem.Relation(
relation = SlashRelationView.Item(
@ -135,6 +143,8 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
)
)
advanceUntilIdle()
val params = CreateBlock.Params(
context = root,
target = a.id,
@ -201,6 +211,9 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
vm.onStart(id = root, space = defaultSpace)
val selection = IntRange(0, 0)
advanceUntilIdle()
vm.apply {
onSelectionChanged(
id = a.id,
@ -235,6 +248,8 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
//TESTING
vm.onSlashItemClicked(
@ -253,6 +268,8 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
)
)
advanceUntilIdle()
val params = ReplaceBlock.Params(
context = root,
target = a.id,
@ -314,6 +331,9 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
// TESTING
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(0, 0)
vm.apply {
@ -350,6 +370,8 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
//TESTING
vm.onSlashItemClicked(
@ -368,6 +390,8 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
)
)
advanceUntilIdle()
vm.controlPanelViewState.test().assertValue { value ->
!value.mainToolbar.isVisible && value.navigationToolbar.isVisible && !value.slashWidget.isVisible
}
@ -410,22 +434,28 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
// TESTING
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(1, 1)
vm.apply {
onSelectionChanged(
id = a.id,
selection = selection
)
advanceUntilIdle()
onBlockFocusChanged(
id = a.id,
hasFocus = true
)
advanceUntilIdle()
onSlashTextWatcherEvent(
SlashEvent.Start(
cursorCoordinate = 100,
slashStart = 1
)
)
advanceUntilIdle()
onSlashTextWatcherEvent(
event = SlashEvent.Filter(
filter = "/",
@ -434,6 +464,8 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
//TESTING
vm.onSlashItemClicked(
@ -452,13 +484,15 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
)
)
advanceUntilIdle()
vm.controlPanelViewState.test().assertValue { value ->
!value.mainToolbar.isVisible && value.navigationToolbar.isVisible && !value.slashWidget.isVisible
}
}
@Test
fun `should remove slash filter after adding new relation`() {
fun `should remove slash filter after adding new relation`() = runTest {
// SETUP
val doc = MockTypicalDocumentFactory.page(root)
val a = MockTypicalDocumentFactory.a
@ -484,7 +518,11 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
)
val vm = buildViewModel()
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val selection = IntRange(1, 1)
//TESTING
@ -526,6 +564,7 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
onSlashItemClicked(SlashItem.Main.Relations)
onSlashItemClicked(SlashItem.RelationNew)
advanceUntilIdle()
//open RelationListScreen
//open RelationCreateScreen
proceedWithAddingRelationToTarget(
@ -534,6 +573,9 @@ class EditorSlashWidgetRelationsTest: EditorPresentationTestSetup() {
)
}
advanceUntilIdle()
val result = vm.blocks.find { it.id == a.id }
assertEquals("Jggig xtstdt ", result?.content<TXT>()?.text)

Some files were not shown because too many files have changed in this diff Show more